[英]Using an order by case in a sub-query
每个时间表都有许多坡度,并且每个坡度都有一个end_date
。
我需要列出所有坡道,以及一个额外的字段,其中包含坡道的ID和该计划的最新结束日期。 我还需要能够在我的WHERE
子句中使用此额外字段。
对于使用MAX
函数的子查询,通常是这种情况,除了一个问题:斜坡的end_date
字段可以为null,表示斜坡是当前的。 因此, SELECT MAX(end_date)
不起作用,因为null
值比非null值“小”。
到目前为止,这是我想出的:
SELECT r1.*,
(SELECT r2.id
FROM ramp as r2
WHERE schedule_id = r.schedule_id
ORDER BY IF(end_dte is NULL, '9999-99-99', end_dte) DESC
LIMIT 1) as latestId
FROM ramp as r1
这将产生此表,这正是我想要的:
+-------+-------------+------------+-----------------+--------+------------+------------+----------+
| id | schedule_id | suppr_flag | comment | months | start_dte | end_dte | latestId |
+-------+-------------+------------+-----------------+--------+------------+------------+----------+
| 16 | 7 | NULL | NULL | NULL | 2008-06-23 | NULL | 16 |
| 15 | 6 | NULL | NULL | NULL | 2007-05-01 | 2007-12-31 | 15 |
| 13 | 5 | NULL | 1-15 deals | NULL | 2004-08-11 | NULL | 13 |
| 11 | 4 | NULL | NULL | NULL | 2005-08-11 | NULL | 11 |
| 12 | 4 | NULL | NULL | 12 | 2004-08-11 | 2005-08-10 | 11 |
| 17 | 13 | NULL | NULL | 6 | 2009-03-05 | 2009-09-04 | 19 |
| 18 | 13 | NULL | NULL | 6 | 2009-09-05 | 2010-03-04 | 19 |
| 19 | 13 | NULL | NULL | NULL | 2010-03-05 | NULL | 19 |
| 20 | 14 | NULL | NULL | 12 | 2001-06-18 | 2008-06-17 | 20 |
除非我不能在WHERE子句中使用latestId
(这是一个未知列)。
你有什么想法?
一种快速的解决方案是在ORDER BY子句上重复整个查询,因为在那里没有看到别名,但是我不太喜欢查询的外观:
SELECT r1.*,
(SELECT r2.id
FROM ramp as r2
WHERE schedule_id = r1.schedule_id
ORDER BY IF(end_dte is NULL, '9999-99-99', end_dte) DESC
LIMIT 1) as latestId
FROM ramp as r1
ORDER BY
(SELECT r2.id
FROM ramp as r2
WHERE schedule_id = r1.schedule_id
ORDER BY IF(end_dte is NULL, '9999-99-99', end_dte) DESC
LIMIT 1);
或者,您可以从原始查询中进行SELECT,然后对结果进行排序:
SELECT s.*
FROM (
SELECT r1.*,
(SELECT r2.id
FROM ramp as r2
WHERE schedule_id = r1.schedule_id
ORDER BY IF(end_dte is NULL, '9999-99-99', end_dte) DESC
LIMIT 1) as latestId
FROM ramp as r1
) s
ORDER BY s.latestId
但是,如果我了解您的逻辑正确性,则可以使用此查询来获取每个schedule_id
的最大end_dte
:
SELECT schedule_id, MAX(COALESCE(end_dte, '9999-12-31')) max_dte
FROM ramp
GROUP BY schedule_id;
然后,您可以再次使用ramp联接此查询,以获取与最大end_dte
关联的ID。 在ON子句中,您将无需再次使用COALESCE:
SELECT r1.schedule_id, r2.id as latestId
FROM (
SELECT schedule_id, MAX(COALESCE(end_dte, '9999-12-31')) max_dte
FROM ramp
GROUP BY schedule_id) r1 INNER JOIN
ramp r2
ON r1.max_dte = COALESCE(r2.end_dte, '9999-12-31')
AND r1.schedule_id = r2.schedule_id
然后,您可以再次加入以获得所需的结果:
SELECT ramp.*, m.latestId
FROM
ramp INNER JOIN (
SELECT r1.schedule_id, r2.id as latestId
FROM (
SELECT schedule_id, MAX(COALESCE(end_dte, '9999-12-31')) max_dte
FROM ramp
GROUP BY schedule_id) r1 INNER JOIN
ramp r2
ON r1.max_dte = COALESCE(r2.end_dte, '9999-12-31')
AND r1.schedule_id = r2.schedule_id
) m ON ramp.schedule_id = m.schedule_id
ORDER BY
latestId
请看这里的小提琴。 请注意,我使用的是“ 9999-12-31”,而不是“ 9999-99-99”,第一个是有效日期,第二个不是有效日期。
编辑
如果您还希望考虑一个以上的schedule_id
共享相同的最大日期这一事实,并且在这种情况下只需要最新的(最大)ID,则可以使用GROUP BY查询和MAX聚合函数:
SELECT r1.schedule_id, MAX(r2.id) as latestId
FROM (
SELECT schedule_id, MAX(COALESCE(end_dte, '9999-12-31')) max_dte
FROM ramp
GROUP BY schedule_id) r1 INNER JOIN
ramp r2
ON r1.max_dte = COALESCE(r2.end_dte, '9999-12-31')
AND r1.schedule_id = r2.schedule_id
GROUP BY
r1.schedule_id
并在主查询中使用此更新版本。
您可以按顺序使用两列...首先是非空指示标志,然后是日期。 改变你拥有的...
ORDER BY IF(end_dte is NULL, '9999-99-99', end_dte) DESC
至
ORDER BY
IF( end_dte is null, 1, 2 ),
end_dte DESC
这样,它将所有“ NULL”结束日期都推到列表的顶部(通过IF()值,对于具有日期的任何其他内容,该值将为1 vs 2),然后按日期降序
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.