关于sql:如何在每个组中仅选择min创建日期的id

How can i select only id of min created date in each group

本问题已经有最佳答案,请猛点这里访问。

想象一下下表

票务表

1
2
3
4
5
 ========================
| id | question          |
 ========================
| 1  | Can u help me :)? |
 ========================

UserEntry表

1
2
3
4
5
6
7
 ======================================================
| id | answer               | dateCreated  | ticket_id |
 ======================================================
| 2  | It's my plessure :)? | 2016-08-05   |     1     |    
=======================================================
| 3  | How can i help u ?   | 2016-08-06   |     1     |
 ======================================================

那么我怎样才能获得每个具有最小日期值的组的行ID

所以我的预期答案应该是这样的

1
2
3
4
5
 ====
| id |
 ====
| 2  |
 ====

更新:

我在下一个查询中得到了解决方案

SELECT id FROM UserEntry WHERE datecreated IN (SELECT MIN(datecreated) FROM CCUserEntry GROUP BY ticket_id)

改进的答案

SELECT id FROM UserEntry WHERE (ticket_id, datecreated) IN
(SELECT ticket_id, MIN(datecreated) FROM UserEntry GROUP BY ticket_id);

这也是一个很好的正确答案(注意:DISTINCT ON不是SQL标准的一部分。)

SELECT DISTINCT ON (ue.ticket_id) ue.id
FROM UserEntry ue
ORDER BY ue.ticket_id, ue.datecreated


您可能需要FETCH FIRST ROW ONLYdistinct on(如果您关心多张票):

1
2
3
SELECT DISTINCT ON (ue.ticket_id) ue.id
FROM UserEntry ue
ORDER BY ue.ticket_id, ue.date_created

这将获得具有最小date_created值的行上的id


您似乎想要选择最小datecreated的ID。这很简单:选择最小日期,然后选择与此日期匹配的ID。

1
SELECT id FROM UserEntry WHERE datecreated = (SELECT MIN(datecreated) FROM UserEntry);

如果你确定你没有关系,或者你只使用一行就可以了,你也可以使用FETCH FIRST ROW ONLY,它在PostgreSQL中没有绑定条款。

1
SELECT id FROM UserEntry ORDER BY datecreated FETCH FIRST ROW ONLY;

更新:您需要每个票证的最小日期的条目ID。每个故障单转换为SQL中的GROUP BY ticket_id

1
2
SELECT ticket_id, id FROM UserEntry WHERE (ticket_id, datecreated) IN
  (SELECT ticket_id, MIN(datecreated) FROM UserEntry GROUP BY ticket_id);

使用只读一次表的窗口函数可以实现同样的效果:

1
2
3
4
5
6
7
SELECT ticket_id, id
FROM
(
  SELECT ticket_id, id, RANK() OVER (PARTITION BY ticket_id ORDER BY datecreated) AS rnk
  FROM UserEntry
) ranked
WHERE rnk = 1;

(如果您希望查询不显示故障单ID,则将SELECT ticket_id, id更改为SELECT id,这会使结果更难理解当然:-)


ANSI SQL的解决方案适用于支持现代SQL的各种DBMS,它使用窗口函数:

1
2
3
4
5
6
SELECT id
FROM (
   SELECT id, ROW_NUMBER() OVER (partition BY ticket_id ORDER BY date_created) AS rn
   FROM userentry
) t
WHERE rn = 1;

请注意,在Postgres中,使用distinct on ()的Gordon解决方案通常比使用窗口函数更快