2013-04-02 16 views
1

每個計劃都有許多坡道,每個坡道都有一個end_date在子查詢中按大小寫使用訂單

我需要列出所有我的坡道,以及包含坡道編號和該計劃的最新結束日期的額外字段。我還需要能夠在我的WHERE條款中使用此額外字段。

對於使用MAX函數的子查詢,這通常是一種情況,除了一個問題:斜坡的end_date字段可以爲空,表示斜坡是當前的。因此,SELECT MAX(end_date)不起作用,因爲null值比非空值「小」。

到目前爲止,這是我想出來的:

SELECT r1.*, 
    (SELECT r2.id 
    FROM ramp as r2 
    WHERE schedule_id = r.schedule_id 
    ORDER BY IF(end_dte is NULL, '9999-99-99', end_dte) DESC 
    LIMIT 1) as latestId 
FROM ramp as r1 

這會產生這個表,這正是我想要的:

+-------+-------------+------------+-----------------+--------+------------+------------+----------+ 
| id | schedule_id | suppr_flag | comment   | months | start_dte | end_dte | latestId | 
+-------+-------------+------------+-----------------+--------+------------+------------+----------+ 
| 16 |   7 | NULL  | NULL   | NULL | 2008-06-23 | NULL  |  16 | 
| 15 |   6 | NULL  | NULL   | NULL | 2007-05-01 | 2007-12-31 |  15 | 
| 13 |   5 | NULL  | 1-15 deals  | NULL | 2004-08-11 | NULL  |  13 | 
| 11 |   4 | NULL  | NULL   | NULL | 2005-08-11 | NULL  |  11 | 
| 12 |   4 | NULL  | NULL   |  12 | 2004-08-11 | 2005-08-10 |  11 | 
| 17 |   13 | NULL  | NULL   |  6 | 2009-03-05 | 2009-09-04 |  19 | 
| 18 |   13 | NULL  | NULL   |  6 | 2009-09-05 | 2010-03-04 |  19 | 
| 19 |   13 | NULL  | NULL   | NULL | 2010-03-05 | NULL  |  19 | 
| 20 |   14 | NULL  | NULL   |  12 | 2001-06-18 | 2008-06-17 |  20 | 

除了我不能在使用latestId WHERE子句(這是一個未知列)。

你有什麼想法嗎?

回答

2

一個快速的解決方案是重複的ORDER BY子句整個查詢,因爲別名是沒見過,但我不喜歡太多的查詢將如何看待:

SELECT r1.*, 
    (SELECT r2.id 
    FROM ramp as r2 
    WHERE schedule_id = r1.schedule_id 
    ORDER BY IF(end_dte is NULL, '9999-99-99', end_dte) DESC 
    LIMIT 1) as latestId 
FROM ramp as r1 
ORDER BY 
    (SELECT r2.id 
    FROM ramp as r2 
    WHERE schedule_id = r1.schedule_id 
    ORDER BY IF(end_dte is NULL, '9999-99-99', end_dte) DESC 
    LIMIT 1); 

或者你從您原來的查詢選擇,並責令其結果:

SELECT s.* 
FROM (
    SELECT r1.*, 
     (SELECT r2.id 
     FROM ramp as r2 
     WHERE schedule_id = r1.schedule_id 
     ORDER BY IF(end_dte is NULL, '9999-99-99', end_dte) DESC 
     LIMIT 1) as latestId 
    FROM ramp as r1 
) s 
ORDER BY s.latestId 

但是,如果我理解你的邏輯correcty,您可以使用此查詢,以獲得最大end_dte每一個schedule_id

SELECT schedule_id, MAX(COALESCE(end_dte, '9999-12-31')) max_dte 
FROM ramp 
GROUP BY schedule_id; 

然後,您可以再次將此查詢與斜坡加入以獲取與最大值end_dte關聯的ID。在ON子句,你會NEET再次使用COALESCE:

SELECT r1.schedule_id, r2.id as latestId 
FROM (
    SELECT schedule_id, MAX(COALESCE(end_dte, '9999-12-31')) max_dte 
    FROM ramp 
    GROUP BY schedule_id) r1 INNER JOIN 
    ramp r2 
    ON r1.max_dte = COALESCE(r2.end_dte, '9999-12-31') 
    AND r1.schedule_id = r2.schedule_id 

然後你就可以再次加入這個得到你需要的結果:

SELECT ramp.*, m.latestId 
FROM 
    ramp INNER JOIN (
    SELECT r1.schedule_id, r2.id as latestId 
    FROM (
     SELECT schedule_id, MAX(COALESCE(end_dte, '9999-12-31')) max_dte 
     FROM ramp 
     GROUP BY schedule_id) r1 INNER JOIN 
     ramp r2 
     ON r1.max_dte = COALESCE(r2.end_dte, '9999-12-31') 
     AND r1.schedule_id = r2.schedule_id 
    ) m ON ramp.schedule_id = m.schedule_id 
ORDER BY 
    latestId 

請參閱小提琴here。請注意,我使用'9999-12-31'而不是'9999-99-99',第一個是有效日期,第二個不是。

編輯

如果你也想考慮的是,不止一個schedule_id共享相同的最大日期,你只需要在這種情況下,最新(最大)ID,您可以使用GROUP BY查詢和MAX彙總功能:

SELECT r1.schedule_id, MAX(r2.id) as latestId 
FROM (
    SELECT schedule_id, MAX(COALESCE(end_dte, '9999-12-31')) max_dte 
    FROM ramp 
    GROUP BY schedule_id) r1 INNER JOIN 
    ramp r2 
    ON r1.max_dte = COALESCE(r2.end_dte, '9999-12-31') 
    AND r1.schedule_id = r2.schedule_id 
GROUP BY 
    r1.schedule_id 

並且您在主要查詢中使用此更新版本。

+0

真的太棒了。我不知道你可以做嵌套的內部連接 ​​- 我嘗試嵌套的子查詢,但它崩潰或不可能。 –

+0

由於某種原因,我得到兩個不同的latestId值。我正在做其他一些連接。任何想法離開你的頭頂? –

+1

@SamSelikoff我認爲對於同一個'schedule_id',可能有不止一行具有相同的最大'end_dte' ...如果這是問題,您是否想要最大ID? – fthiella

0

您可以在您的訂單中使用兩列...首先是非空指示標誌,然後是日期。改變你的...

ORDER BY IF(end_dte is NULL, '9999-99-99', end_dte) DESC 

ORDER BY 
    IF(end_dte is null, 1, 2), 
    end_dte DESC 

這樣,就全押「NULL」結束日期到列表的頂部(通過IF()值是1比2的其他任何東西,有個約會),那麼,按日期遞減