Mysql 在子查询中使用按案例排序
每个明细表都有许多坡道,每个坡道都有一个Mysql 在子查询中使用按案例排序,mysql,sql,Mysql,Sql,每个明细表都有许多坡道,每个坡道都有一个结束日期 我需要列出我的所有坡道,以及一个额外的字段,该字段包含坡道id以及该计划的最新结束日期。我还需要能够在我的WHERE子句中使用这个额外字段 这通常是使用MAX函数的子查询的情况,但有一个问题除外:渐变的end\u date字段可以为空,表示渐变为当前渐变。因此,SELECT MAX(end_date)不起作用,因为null值比非null值“小” 到目前为止,我的想法是: SELECT r1.*, (SELECT r2.id FRO
结束日期
我需要列出我的所有坡道,以及一个额外的字段,该字段包含坡道id以及该计划的最新结束日期。我还需要能够在我的WHERE
子句中使用这个额外字段
这通常是使用MAX
函数的子查询的情况,但有一个问题除外:渐变的end\u date
字段可以为空,表示渐变为当前渐变。因此,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 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
但是,如果我正确理解了您的逻辑,您可以使用此查询来获取每个计划id的最大结束日期
:
SELECT schedule_id, MAX(COALESCE(end_dte, '9999-12-31')) max_dte
FROM ramp
GROUP BY schedule_id;
然后,您可以再次将此查询与ramp连接,以获取与最大end\u 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”,第一个是有效日期,第二个不是
编辑
如果您还希望考虑一个以上的代码< > TopeSyid ID/COD>共享相同的最大日期,并且在这种情况下只需要最新的(最大)ID,就可以使用逐组查询和最大聚合函数:
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
到
通过这种方式,它将所有“空”结束日期推到列表的顶部(通过IF()值,对于任何其他有日期的日期,都将是1 vs 2),然后,通过日期降序,这真是太棒了。我不知道你可以做嵌套的内部连接-我尝试了嵌套的子查询,但它要么崩溃了,要么不可能。出于某种原因,我得到了两行不同的latestId值。我正在做一些其他的连接。你脑子里有什么想法吗?@SamSelikoff我想对于同一个计划id
,可能不止一行有相同的最大值end\dte
。。。如果这就是问题所在,你只需要最大ID吗?啊,是的,我明白了。这是一个数据完整性问题(这很好,它指出了错误)。如果我只是想要最大ID,我会怎么做?谢谢,顺便说一句,你太棒了。@SamSelikoff谢谢:)你可以使用带有最大聚合函数的分组,我更新了我的答案。。我在开头还添加了一个问题,这只是一个不同的想法。。。我希望最后的查询是你要找的!
ORDER BY
IF( end_dte is null, 1, 2 ),
end_dte DESC