2009-09-29 23 views
1

我正在處理對我來說一個複雜的查詢,並且我已經設法獲取我需要的信息,但似乎被迫創建一個表來完成它。我正在使用MySQL,所以我不能使用WITH,我不能使用視圖,因爲我的SELECTFROM子句中包含子查詢,並且我不能使用臨時表,因爲我需要自聯接。我錯過了什麼嗎?SQL查詢:子查詢上的自加入需要創建一個單獨的(非臨時)表?

背景:

  • 一個reservation可以具有1個或多個reservation_detail(上reservation_id外鍵rel'p)
  • 一個reservation_detail具有quantityticket_type(上ticket_type外鍵rel'p)

這是我目前解決方案的第一部分:

CREATE TABLE 
    tmp 
SELECT 
    t.reservation_id, 
    t.ticket_type, 
    COALESCE(rd.quantity,0) AS qty 
FROM (
    SELECT * 
    FROM 
     (ticket_type tt, reservation r) 
    ) t 
LEFT JOIN 
    reservation_detail rd 
    ON 
     t.reservation_id = rd.reservation_id 
    AND 
     t.ticket_type = rd.ticket_type; 

這給了我一個表,如下所示,其中用於reservation_idticket_type的每一個組合,我有一個qty

+----------------+-------------+------+ 
| reservation_id | ticket_type | qty | 
+----------------+-------------+------+ 
|    1 | ADULT  | 2 | 
|    1 | CHILD  | 2 | 
|    1 | INFANT  | 0 | 
|    2 | ADULT  | 1 | 
|    2 | CHILD  | 0 | 
|    2 | INFANT  | 0 | 
|    3 | ADULT  | 1 | 
|    3 | CHILD  | 0 | 
|    3 | INFANT  | 0 | 
+----------------+-------------+------+ 

現在我可以自己加入三次在此表中得到什麼,我真的找...

SELECT 
    t1.reservation_id, 
    t1.qty AS num_adults, 
    t2.qty AS num_children, 
    t3.qty AS num_infants 
FROM 
    tmp t1 
LEFT JOIN 
    tmp t2 
    ON 
     t1.reservation_id = t2.reservation_id 
LEFT JOIN 
    tmp t3 
    ON 
     t2.reservation_id = t3.reservation_id 
WHERE 
    t1.ticket_type = 'ADULT' 
AND 
    t2.ticket_type = 'CHILD' 
AND 
    t3.ticket_type = 'INFANT'; 

...這是用於顯示每個數量各保留一個排三種票類型。

+----------------+------------+--------------+-------------+ 
| reservation_id | num_adults | num_children | num_infants | 
+----------------+------------+--------------+-------------+ 
|    1 |   2 |   2 |   0 | 
|    2 |   1 |   0 |   0 | 
|    3 |   1 |   0 |   0 | 
+----------------+------------+--------------+-------------+ 

我希望這是足夠的信息。如果不是,請留下評論。然而

SELECT reservation_id, 
     SUM(CASE WHEN ticket_type='ADULT' THEN qty ELSE 0 END) AS adults, 
     SUM(CASE WHEN ticket_type='CHILD' THEN qty ELSE 0 END) AS children, 
     SUM(CASE WHEN ticket_type='INFANT' THEN qty ELSE 0 END) AS infants, 
FROM tmp 
GROUP BY reservation_id; 

,我想知道一下自己的模式:

+1

感謝大家迅速答覆。我每天都在學習更多關於優秀SQL查詢的力量:) – nselikoff 2009-09-29 16:53:09

回答

1

如果要堅持你的第一個查詢,您可以Sub此爲第二。您正在存儲qty,一個計算值。您是否考慮過爲每個故障單實例設置一行?如果你這樣做,那麼不需要tmp表,儘管你可以像上面那樣做轉軸。

+0

逗號補充。樂意效勞。 – dnagirl 2009-09-29 16:59:25

0

簡單GROUP BY應該是OK:

SELECT t.reservation_id, 
     SUM(CASE 
       WHEN ticket_type = 'ADULT' THEN 
       COALESCE(rd.quantity, 0) 
       ELSE 
       0 
      END) num_adults, 
     SUM(CASE 
       WHEN ticket_type = 'CHILD' THEN 
       COALESCE(rd.quantity, 0) 
       ELSE 
       0 
      END) num_children, 
     SUM(CASE 
       WHEN ticket_type = 'INFANT' THEN 
       COALESCE(rd.quantity, 0) 
       ELSE 
       0 
      END) num_infants 
    FROM (SELECT * FROM (ticket_type tt, reservation r)) t 
    LEFT JOIN reservation_detail rd ON t.reservation_id = rd.reservation_id 
           AND t.ticket_type = rd.ticket_type 
GROUP BY t.reservation_id 
+0

這也適用,謝謝。我選擇了另一個查詢,因爲它在我的測試機器上執行速度稍快。 – nselikoff 2009-09-29 16:50:34

1

由於表reservation_detail包含您需要的所有字段,因此不需要連接其他表並創建臨時表。

試試這個:

SELECT distinct 
    t.reservation_id, 
    COALESCE(t1.qty,0) AS num_adults, 
    COALESCE(t2.qty,0) AS num_children, 
    COALESCE(t3.qty,0) AS num_infants 
FROM reservation t 
LEFT JOIN reservation_detail t1 ON t.reservation_id = t1.reservation_id AND t1.ticket_type = 'ADULT' 
LEFT JOIN reservation_detail t2 ON t.reservation_id = t2.reservation_id AND t2.ticket_type = 'CHILD' 
LEFT JOIN reservation_detail t3 ON t.reservation_id = t3.reservation_id AND t3.ticket_type = 'INFANT'; 
+0

我看到了你要去的地方,但這兩個查詢都不適用於我的情況,因爲預留並不一定包含每個reservation_detail如果所有預訂都有每個票證類型的條目,則這些查詢纔有效 – nselikoff 2009-09-29 16:38:15

+0

我更新了我的第二個查詢以滿足您的新需求,請再試一次 – RedFilter 2009-09-29 16:42:09

+0

已將其清除,因此只有一個查詢 – RedFilter 2009-09-29 16:43:12