每个时间表都有很多斜坡,每个斜坡都有一个end_date
。
我需要列出我的所有斜坡,以及一个额外的字段,其中包含斜坡的id以及该时间表的最新结束日期。我还需要能够在WHERE
子句中使用这个额外的字段。
这通常是使用MAX
函数的子查询的情况,除了一个问题:渐变的end_date
字段可以为空,表示斜坡是当前的。因此,SELECT MAX(end_date)
不起作用,因为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
(它是一个未知的列)。
你有什么想法吗?
答案 0 :(得分:2)
快速解决方案是在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 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
但如果我理解您的逻辑是正确的,那么您可以使用此查询为每个end_dte
获取最大schedule_id
:
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
请参阅小提琴here。请注意,我使用的是'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
并在主查询中使用此更新版本。
答案 1 :(得分:0)
您可以在订单中使用两列...首先是非空指示标志,然后是日期。改变你的......
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对2对于其他任何有日期的东西),然后,按日期降序