2011-11-25 74 views
5

这种鲜明的价值一行是数据选择与一列

id name  start_date end_date merchant_id 
=================================================== 
111 name1 25-nov-11 31-jan-12 9999 
222 name2 23-nov-11 25-dec-11 9999 
333 name3 25-nov-11 25-nov-12 9999 
444 name4 20-nov-11 20-nov-11 9999 
555 name5 25-nov-11 25-dec-11 8888 
666 name6 19-oct-11 20-nov-11 8888 
777 name7 20-nov-11 20-jun-12 8888 

我需要通过start_date(DESC)排序的所有行start_date<=todayend_date >=today但每merchant_id限1。这意味着如果查询发现多于一行,则返回第一个。


测试脚本

CREATE TABLE DEAL 
(
    ID   VARCHAR2(40 BYTE)  NOT NULL, 
    NAME   VARCHAR2(255 BYTE), 
    START_DATE DATE, 
    END_DATE  DATE, 
    MERCHANT_ID NUMBER(22), 
CONSTRAINT DEAL PRIMARY KEY (ID) 
); 

INSERT ALL 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('111','name1','25-nov-11','31-jan-12','9999') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('222','name2','23-nov-11','25-dec-11','9999') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('333','name3','25-nov-11','25-nov-12','9999') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('444','name4','20-nov-11','20-nov-11','9999') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('555','name5','25-nov-11','25-dec-11','8888') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('666','name6','19-oct-11','20-nov-11','8888') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('777','name7','20-nov-11','20-jun-12','8888') 
SELECT * FROM dual; 

运行以下命令:

MERCHANT_ID ID NAME START_DATE END_DATE 
=========================================== 
9999   111 name1 25-NOV-11 31-JAN-12 
9999   333 name3 25-NOV-11 25-NOV-12 
8888   555 name5 25-NOV-11 25-DEC-11 
9999   222 name2 23-NOV-11 25-DEC-11 
8888   777 name7 20-NOV-11 20-JUN-12 

为同一商家ID多次返回
SELECT DISTINCT merchant_id, id, name, start_date, end_date FROM deal WHERE start_date <= trunc(sysdate) AND end_date >= trunc(sysdate) ORDER BY start_date DESC; 

不返回预期的结果

+0

可以使用BETWEEN子句来代替起始日期<=今天日期和结束日期> =今天。 –

+0

我一直在尝试各种不同的声明,不同的,限制,组.. ..但一直没能得到任何工作。我可以得到具有适当的开始和结束日期的所有行,但不知道如何返回1行每merchant_id –

+0

您使用哪个数据库?如果您使用的是Oracle一个解决方案是使用分析功能 – Giovanni

回答

2

以下Oracle查询应该做你需要的东西:

SELECT * 
FROM (
    SELECT TABLE1.*, DENSE_RANK() OVER(PARTITION BY MERCHANT_ID ORDER BY START_DATE DESC, ID) R 
    FROM TABLE1 
    WHERE SYSDATE BETWEEN START_DATE AND END_DATE 
) 
WHERE R = 1 
ORDER BY START_DATE DESC 

实质上,它首先按日期过滤行,然后忽略除共享相同MERCHANT_ID的第一个之外的所有行。

请注意,“first”的含义是根据降序START_DATE顺序定义的。它的两行具有相同的START_DATE,则使用ID顺序解决“争议”。

+0

完美!谢谢! –

0

嗨这样的事情可以工作:

select id, name,  start_date, end_date from (
select id, name,  start_date, end_date, ROW_NUMBER() 
    OVER (PARTITION BY merchant_id ORDER BY merchant_id) AS rnum from your_table 
    where start_date<=trunc(sysdate) and end_date>=trunc(sysdate)) 
    where rnum=1 
order by start_date desc 

如果用于创建和填充表,我可以给你正确的查询提供了一个简单的测试脚本。

+0

将测试脚本添加到原始文章中。 –

0

根据你正在运行的SQL类型(mysql,sql server等),会有替代答案。

例如,在SQL Server,你可以说“分配各行的数量,从1开始的每个商家”,并总是挑号码1.

在通用的SQL,你必须要少一点直接。它看起来你的ID列保证是唯一的?如果是这样,问题的一种表达方式是“在日期范围内获取记录,在同一商家的同一日期范围内没有更高的ID”

您是否已经知道如何过滤>和<?我想答案要怎么做特定于你使用什么类型的SQL:

所以尝试:

SELECT * from myFavoriteTable 
    WHERE today() < end_date and today > start_date -- for this date criteria use whatever works 
    AND NOT EXISTS (SELECT * from myFavoriteTable as TooLow 
     WHERE today() < end_date and today() > start_date -- as above 
     AND TooLow.Merchant = myFavoriteTable.merchant 
     AND TooLow.id > myFavoriteTable.id) 
+0

SQL是针对Oracle的。 –

-1

所有这些其他答案看起来都很复杂......您可以使用Oracle中的DISTINCT修饰符为每个特定列获取一个且唯一一个唯一行。这里是你可以用它来获取你想要的数据的查询,因为在您的文章表结构:

SELECT DISTINCT merchant_id, id, name, start_date, end_date FROM table WHERE start_date >= today AND end_date < today ORDER BY start_date DESC

+0

这不会返回所需的结果 SELECT DISTINCT merchant_id,id,name,start_date,end_date FROM deal WHERE start_date <= trunc(sysdate)AND end_date> = trunc(sysdate)ORDER BY start_date DESC; –

+0

不会为单个列返回不同的行 – Sasi