繁体   English   中英

(My)SQL:如果子查询不是空集,则返回子查询

[英](My)SQL: If subquery is not an empty set, return subquery

这个问题专门针对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

我的解决方案可行,但我希望有一个更优雅,更重复的解决方案。

通用解决方案将是一种解决方案-如果存在子查询,则返回子查询中的值; 否则,可以返回其他内容。

代替子查询,进行左联接(到表本身)

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()函数返回其第一个参数,不为null。

针对您自己的回答,我建议使用:

SELECT
  COALESCE((
    SELECT MIN(start_date)
    FROM TABLE
    WHERE start_date > ? 
    AND   identifier = ?), (
    SELECT
      DATE_ADD(?, INTERVAL 30 DAY)
    )) AS end_date 

似乎更容易理解恕我直言。 即使外观不同,它在后台所做的事情几乎相同。

根据fancyPant的解决方案,我使用了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语句的第一个参数,第二个查询是替代查询。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM