我有一个名为“事件”的表,并希望在“ created_at”日期之前获取第一个条目。但是,如果第一个事件(MIN(events.created_at))的标题包含“ test”,则我想返回该用户的下一个事件(由created_at决定)。如果用户只有一个事件,则只需返回该事件。
有没有一种简单的方法可以通过查询执行此操作?
这是我所能获得的。它通过created_at
返回第一个事件SELECT MIN(events.created_at) 'event_created_at', events.user_id, events.title, MIN(events.type) 'type'
FROM events
GROUP BY events.user_id
这是用于SQL DBMS
答案 0 :(得分:2)
我认为您确实想要有关该事件的完整信息。如果是这样,GROUP BY
是错误的方法。
select e.*
from (select e.*,
row_number() over (partition by e.user_id
order by (case when e.title not like '%test%' then 1 else 2 end) desc,
e.created_at asc
) as seqnum
from events e
) e
where seqnum = 1;
当您要从组中选择行时,通常使用窗口函数比group by
更好。
答案 1 :(得分:0)
对于SQL Server,WITH TIES
将是一个不错的选择
select top 1 with ties
events.user_id
,events.title
,events.created_at
,events.type
from events
order by row_number() over (partition by events.user_id order by case when events.title = 'test' then 2 else 1 end, events.created_at)
答案 2 :(得分:0)
编辑:戈登击败了我。在发布答案之前,请教我不要刷新。我同意,但是要使用Window Function。我和他的唯一的区别是检查NULL
created_at
日期。
MS SQL Server 2017架构设置:
CREATE TABLE events ( user_id int, title varchar(20), type varchar(20), created_at datetime ) ;
INSERT INTO events ( user_id, title, type, created_at )
VALUES
( 1, 'Event1', 'Event', '2018-01-01 00:00:00.000' ) /* This one */
, ( 2, 'Event1', 'Event', '2018-05-01 00:00:00.000' )
, ( 2, 'Event1', 'Event', '2018-06-01 00:00:00.000' )
, ( 1, 'Event2', 'Event', '2018-11-22 00:00:00.000' )
, ( 5, 'Event2', 'test', '2018-11-22 00:00:00.000' )
, ( 5, 'Event2', 'Event', '2018-01-02 00:00:00.000' ) /* This one */
, ( 5, 'Event3', 'TesT', '2018-01-03 00:00:00.000' )
, ( 5, 'Event3', 'NoTest', '2018-01-03 00:00:00.000' ) /* This one */
, ( 4, 'Event3', 'test', '2018-01-01 00:00:00.000' )
, ( 1, 'Event4', 'TeSt', '2018-01-04 00:00:00.000' ) /* This one */
, ( 2, 'Event5', 'Event', null )
, ( 3, 'Event5', 'Event', '2018-01-05 00:00:00.000' ) /* This one */
, ( 4, 'Event6', 'test', '2018-01-07 00:00:00.000' )
, ( 4, 'Event6', 'test', '2018-01-06 00:00:00.000' ) /* This one */
;
主要查询:
SELECT s1.created_at AS event_created_at
, s1.user_id
, s1.title
, s1.type
FROM (
SELECT e.title, e.user_id, e.type, e.created_at
, ROW_NUMBER() OVER (
PARTITION BY e.title
ORDER BY e.title, CASE WHEN e.type='test' THEN 1 ELSE 2 END DESC, e.created_at
) AS rn
FROM events e
WHERE e.created_at IS NOT NULL
) s1
WHERE s1.rn = 1
Results :
| event_created_at | user_id | title | type |
|----------------------|---------|--------|--------|
| 2018-01-01T00:00:00Z | 1 | Event1 | Event |
| 2018-01-02T00:00:00Z | 5 | Event2 | Event |
| 2018-01-03T00:00:00Z | 5 | Event3 | NoTest |
| 2018-01-04T00:00:00Z | 1 | Event4 | TeSt |
| 2018-01-05T00:00:00Z | 3 | Event5 | Event |
| 2018-01-06T00:00:00Z | 4 | Event6 | test |