这个问题专门针对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
我的解决方案有效,但我希望有一个更优雅,非重复的解决方案。
通用解决方案是 - 如果子查询存在 - 返回子查询中的值;否则,可以返回其他内容。
答案 0 :(得分: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
左连接条目要么存在要么不存在,这意味着它不是null或null。 COALESCE()函数返回其第一个非空的参数。
答案 1 :(得分:1)
根据您自己的回答,我建议使用:
SELECT
COALESCE((
SELECT MIN(start_date)
FROM TABLE
WHERE start_date > ?
AND identifier = ?), (
SELECT
DATE_ADD(?, INTERVAL 30 DAY)
)) AS end_date
似乎更容易理解恕我直言。即使它看起来不同,它几乎在幕后做同样的事情。
答案 2 :(得分:0)
根据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
语句的第一个参数,另一个查询是第二个参数。