(My)SQL:如果子查询不是空集,则返回子查询
Posted
技术标签:
【中文标题】(My)SQL:如果子查询不是空集,则返回子查询【英文标题】:(My)SQL: If subquery is not an empty set, return subquery 【发布时间】:2017-06-14 13:01:34 【问题描述】:这个问题是专门针对 mysql 的,但我试图以适用标准 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
我的解决方案有效,但我希望有一个更优雅、不重复的解决方案。
一般的解决方案是——如果存在子查询——从子查询返回值;否则,可以退回其他东西。
【问题讨论】:
【参考方案1】:代替子查询做一个左连接(到表本身)
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
的工作方式。您加深了我对该功能的理解,使我能够开发我标记为已接受的解决方案(一旦我可以这样做)。谢谢!【参考方案2】:
针对您自己的回答,我建议使用:
SELECT
COALESCE((
SELECT MIN(start_date)
FROM TABLE
WHERE start_date > ?
AND identifier = ?), (
SELECT
DATE_ADD(?, INTERVAL 30 DAY)
)) AS end_date
似乎更容易理解恕我直言。尽管它看起来不同,但它在幕后做的事情几乎相同。
【讨论】:
更有效,没有ORDER BY
语句,而且你这么清楚地指出我完全忘记了MIN()
是一个函数!成功。标记为已接受(主要是因为我不想标记我自己问题的答案,但也因为你的解决方案更好)。【参考方案3】:
根据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
语句的第一个参数,备用查询是第二个。
【讨论】:
以上是关于(My)SQL:如果子查询不是空集,则返回子查询的主要内容,如果未能解决你的问题,请参考以下文章