(My)SQL:如果子查询不是空集,返回子查询
这个问题专门针对MySQL,但我试图以标准SQL适用的方式提问。(My)SQL:如果子查询不是空集,返回子查询
语境:我试图确定以下列方式结束日期:是否存在用户输入的开始日期之后另一个起始日期,使用现有的开始日期为结束日期;否则,结束日期应在输入的开始日期后30天。
我已经试过的解决方案是类似以下内容:
SELECT
IF(
EXISTS(
SELECT
DISTINCT start_date
FROM table
WHERE ? < start_date AND
identifier = ?
ORDER BY start_date
LIMIT 1
), (
SELECT
DISTINCT start_date
FROM table
WHERE ? < start_date AND
identifier = ?
ORDER BY start_date
LIMIT 1),
DATE_ADD(?, INTERVAL 30 DAY)
) AS end_date
我的解决方案的工作,但我希望有一个更优雅的,不重复的解决方案。如果子查询存在,则—返回子查询中的值;否则,可能会返回其他内容。
在回答自己的答案,我会建议使用:
SELECT
COALESCE((
SELECT MIN(start_date)
FROM TABLE
WHERE start_date > ?
AND identifier = ?), (
SELECT
DATE_ADD(?, INTERVAL 30 DAY)
)) AS end_date
似乎更容易理解恕我直言。即使它看起来不同,它在幕后几乎做了同样的事情。
而不是一个子查询的做左连接(表本身)
SELECT
COALESCE(t2.start_date, t1.start_date)
FROM table t1
LEFT JOIN table t2 ON t1.identifier = t2.identifier AND t1.start_date > t2.start_date
左侧加入条目或者是有还是没有,这意味着它不为空或空。 COALESCE()函数返回其非空的第一个参数。
该解决方案是生产矿山不可或缺的;尽管'JOIN'语句并不完全符合我想要做的,但我不熟悉'COALESCE'是如何工作的。你对我对这个功能的理解的进一步让我能够开发出我认为被接受的解决方案(一旦我可以这么做)。谢谢! – Mattallurgy
根据fancyPants的解决方案,我使用COALESCE
,但采用了截然不同的方式(因此我不能完全将响应标记为已接受)。
SELECT
COALESCE((
SELECT
DISTINCT start_date
FROM TABLE
WHERE ? < start_date AND
identifier = ?
ORDER BY start_Date
LIMIT 1), (
SELECT
DATE_ADD(?, INTERVAL 30 DAY)
)) AS end_date
上述查询将按照预期完成。您的子查询是COALESCE
声明的第一个参数,另一个查询是第二个。
更有效,没有'ORDER BY'语句,你清楚地指出我完全忘记了'MIN()'是一个函数!成功。标记为已接受(主要是因为我不想标记自己的问题的答案,但也因为你是一个更好的解决方案)。 – Mattallurgy