2017-06-08 49 views
3

基本上,我需要检索在至少两个不同日期购买的客户的最后两个日期,这意味着有一些客户只在一个日期购买,数据有下面的表格获得每个客户的最近两个日期

client_id date 
1   2016-07-02 
1   2016-07-02 
1   2016-06-01 
2   2015-06-01 

,我想获得它下面的表单

client_id  previous_date  last_date 
1    2016-06-01  2016-07-02 

remarques:

客户端可以对sa多个条目我至今

客户端可以将条目只为一个日期,这样的客户应该丢弃

回答

2

DENSE_RANK排序日期。然后按client_id分组并显示最后日期(排名#1和#2)。

select 
    client_id, 
    max(case when rn = 2 then date end) as previous_date, 
    max(case when rn = 1 then date end) as last_date 
from 
(
    select 
    client_id, 
    date, 
    dense_rank() over (partition by client_id order by date desc) as rn 
    from mytable 
) 
group by client_id 
having max(rn) > 1; 
+0

嗯,我刚刚注意到我的答案没有增加太多,因为xQbert已经发布了大致相同的内容(尽管存在一些小缺陷)。 –

+0

是的,但你的并没有我的缺点:P – xQbert

1

UNTESTED:

我们使用公用表表达式来分配降序基于日期的行数和那么只包括那些行号为< = 2的记录,然后确保具有1行的那些记录被排除。

WITH CTE AS (
    SELECT Distinct Client_ID 
     , Date 
     , row_number() over (partition by clientID order by date desc) rn 
    FROM Table) 

SELECT Client_ID, min(date) previous_date, max(date) last_date) 
FROM CTE 
WHERE RN <=2 
GROUP BY Client_ID 
HAVING max(RN) > 1 
+0

看起来相当好。将'row_number'更改为'dense_rank',因为可能有重复的日期。在'HAVING'之前插入'GROUP BY Client_ID'。在'last_date'后删除prenthesis。 –

+0

我想我可以区分日期,因为预期的结果似乎不希望重复的日期。或者我会有不同的第一个然后得到行号。在我这样做之前,我从不确定这种操作顺序。但密集排名可能比我的方法更快。 – xQbert

1

所有你需要的是一组由...

--test date 
declare @tablename TABLE 
(
    client_id int, 
    [date] datetime 
); 

insert into @tablename 
values(1 , '2016-07-02'), 
    (1 , '2016-07-02'), 
    (1 , '2016-06-01'), 
    (2 , '2015-06-01'); 

--query 
SELECT client_id,MIN([DATE]) AS [PREVIOUS_DATE], MAX([DATE]) AS [LAST_DATE] 
FROM @tablename 
GROUP BY client_id 

更新

-- create data 
create table myTable 
(
    client_id integer, 
    given_date date 
); 

insert into myTable 
values(1 , '2016-07-02'), 
    (1 , '2016-07-02'), 
    (1 , '2016-06-01'), 
    (1 , '2016-06-03'), 
    (1 , '2016-06-09'), 
    (2 , '2015-06-01'), 
    (3 , '2016-06-03'), 
    (3 , '2016-06-09'); 

-- query 
SELECT sub.client_id, sub.PREVIOUS_DATE, sub.LAST_DATE 
FROM 
(select 
    ROW_NUMBER() OVER (PARTITION BY a.client_id order by b.given_date desc,(MAX(b.given_date) - a.given_date)) AS ROW_NUMBER, 
    a.client_id,a.given_date AS PREVIOUS_DATE, MAX(b.given_date) - a.given_date AS diff, (b.given_date) AS LAST_DATE 
    FROM myTable AS a 
     JOIN myTable AS b 
     ON b.client_id = a.client_id 
    WHERE a.given_date <> b.given_date 
    group by a.client_id, a.given_date, b.given_date) AS sub 
WHERE sub.ROW_NUMBER = 1 
+0

如果你打算投我的asnwer,是男人足以说方式,所以我可以修复它.. – chris

+0

我没有downvote。但是,您的查询也会选择只有一个日期的客户。对于有两个以上日期的客户,它将返回错误的结果。名称周围的括号是非标准的。我认为SQL Server和MS Access使用它们,但几乎没有其他的DBMS。 PostgreSQL不会。 –

+0

@ThorstenKettner,谢谢。我在T-SQL中工作的更多部分,刚开始回到这里,并没有'注意到postgresql标签。此外,对我来说,请求并不明确,但在阅读您的评论和其他一些帖子后,我重新编写了我的脚本。可以在http://sqlfiddle.com/#!15/55677进行测试。 – chris

1

建立:

t=# create table s153 (c int, d date); 
CREATE TABLE 
t=# insert into s153 values (1,'2016-07-02'), (1,'2016-07-02'),(1,'2016-06-01'),(2,'2016-06-01'); 
INSERT 0 4 

查询:

t=# with a as (
select distinct c,d from s153 
) 
, b as (
select c,nth_value(d,1) over (partition by c order by d) last_date, nth_value(d,2) over (partition by c order by d) prev_date 
from a 
) 
select * from b where prev_date is not null 
; 
c | last_date | prev_date 
---+------------+------------ 
1 | 2016-06-01 | 2016-07-02 
(1 row) 
相关问题