简体   繁体   English

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

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

This question is directed specifically toward MySQL, but I'm trying to ask it in such a way that standard SQL is applicable. 这个问题专门针对MySQL,但我试图以适用标准SQL的方式询问它。

Context: I am trying to determine an end date in the following way: if there exists another start date after the entered start date, use the existing start date as the end date; 上下文:我正在尝试通过以下方式确定结束日期:如果在输入的开始日期之后存在另一个开始日期,请使用现有的开始日期作为结束日期; otherwise, the end date should be 30 days after the entered start date. 否则,结束日期应为输入的开始日期之后的30天。

The solution I've tried is similar to the following: 我尝试过的解决方案类似于以下内容:

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

My solution works, but I was hoping there were a more elegant, non-repetitive solution. 我的解决方案可行,但我希望有一个更优雅,更重复的解决方案。

The generic solution would be one which—if a subquery exists—returns the values from the subquery; 通用解决方案将是一种解决方案-如果存在子查询,则返回子查询中的值; otherwise, something else can be returned. 否则,可以返回其他内容。

Instead of a subquery do a left join (to the table itself) 代替子查询,进行左联接(到表本身)

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

The left joined entry is either there or it is not, which means it is not null or null. 左连接的条目是存在还是不存在,这意味着它不是null或null。 The COALESCE() function returns the first of its arguments which is not null. COALESCE()函数返回其第一个参数,不为null。

In response to your own answer I'd suggest to use: 针对您自己的回答,我建议使用:

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

Seems easier to understand IMHO. 似乎更容易理解恕我直言。 And even though it looks different, it pretty much does the same things behind the scenes. 即使外观不同,它在后台所做的事情几乎相同。

As per fancyPants ' solution, I used COALESCE , but in a radically different way (hence why I can't entirely mark the response as accepted). 根据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

The above query will do precisely as intended. 上面的查询将完全按预期执行。 Your subquery is the first argument of the COALESCE statement, and the alternative query is the second. 您的子查询是COALESCE语句的第一个参数,第二个查询是替代查询。

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

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