2016-05-09 6 views
0

У меня есть таблица с примерно 8 миллионами строк. Строки содержат идентификатор, дату и код события. Я хотел бы выбрать все ID и даты, для которых код события равен 1, и в прошлом был код события, равный 2 в прошлом.SQL Server 2012 SELECT max date на основе нескольких условий

Например, моя таблица выглядит следующим образом:

ID Date  Code 
---------------------- 
1  4/16/2016 6 
1  4/10/2016 1 
1  3/1/2016 13 
1  1/26/2016 2 
2  5/2/2016 8 
2  3/14/2016 1 
2  1/13/2016 14 

Я хотел бы ID = 1 и Date = 4/10/2016 вернулся, но я не хотел бы что-нибудь вернулся с ID = 2, так как ID = 2 никогда не было кода события, равного 2.

Как написать свое заявление SELECT, чтобы получить эти результаты?

+0

Я дам вам подсказку: Вы хотите 'SELECT * FROM TABLE WHERE Code = 1 AND' .... что-то еще –

+0

Может "1" появится более чем один раз для данного идентификатора? –

ответ

1

Если вы только хотите, чтобы выбрать дату макс для каждого ID:

WITH Cte AS(
    SELECT *, 
     rn = ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Date DESC) 
    FROM tbl 
    WHERE Code = 1 
) 
SELECT 
    ID, Date, Code 
FROM Cte c 
WHERE 
    rn = 1 
    AND EXISTS(
     SELECT 1 
     FROM tbl t 
     WHERE 
      t.ID = c.ID 
      AND t.Date < c.Date 
      AND t.Code = 2 
    ) 
; 

ONLINE DEMO


Использование MAX, GROUP BY и HAVING:

SELECT 
    ID, Date = MAX(Date) 
FROM tbl t1 
WHERE Code = 1 
GROUP BY t1.ID 
HAVING MAX(Date) > (SELECT Date FROM tbl t2 WHERE t2.ID = t1.ID AND t2.Code = 2) 

ONLINE DEMO

1

Вы можете использовать exists.

select * 
from t 
where code = 1 and 
     exists (select 1 from t t1 where t.id = t1.id and t.dt > t1.dt and t1.code=2) 
+0

просто нужно высунуть 'AND' там –

0
select id 
, max(date) 
from table to 
where to.code = 1 
and exists (select 1 from table ti where ti.id = to.id AND ti.code = 2) 
group by id 
0

@vkp имеет лучший ответ. Но, вот подход с использованием оконных функций:

select t.id, t.code, t.dt 
from (select t.*, min(case when code = 2 then dt end) over (partition by id) as dt_2 
     from t 
     where code in (1, 2) 
    ) t 
where t.code = 1 and dt_2 < dt;