2017-06-14 234 views
0

這個問題專門針對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 

我的解決方案的工作,但我希望有一個更優雅的,不重複的解決方案。如果子查詢存在,則—返回子查詢中的值;否則,可能會返回其他內容。

回答

1

在回答自己的答案,我會建議使用:

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

似乎更容易理解恕我直言。即使它看起來不同,它在幕後幾乎做了同樣的事情。

+0

更有效,沒有'ORDER BY'語句,你清楚地指出我完全忘記了'MIN()'是一個函數!成功。標記爲已接受(主要是因爲我不想標記自己的問題的答案,但也因爲你是一個更好的解決方案)。 – Mattallurgy

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()函數返回其非空的第一個參數。

+0

該解決方案是生產礦山不可或缺的;儘管'JOIN'語句並不完全符合我想要做的,但我不熟悉'COALESCE'是如何工作的。你對我對這個功能的理解的進一步讓我能夠開發出我認爲被接受的解決方案(一旦我可以這麼做)。謝謝! – Mattallurgy

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聲明的第一個參數,另一個查詢是第二個。