2010-05-26 17 views
3

所以,我有一個查詢,看起來像這樣:如何分解SQL查詢中的重複表達式?列的別名似乎並沒有成爲售票

SELECT id, 
    DATE_FORMAT(CONVERT_TZ(callTime,'+0:00','-7:00'),'%b %d %Y') as callDate, 
    DATE_FORMAT(CONVERT_TZ(callTime,'+0:00','-7:00'),'%H:%i') as callTimeOfDay, 
    SEC_TO_TIME(callLength) as callLength 
FROM cs_calldata WHERE 
    customerCode='999999-abc-blahblahblah' AND 
    CONVERT_TZ(callTime,'+0:00','-7:00') >= '2010-04-25' AND 
    CONVERT_TZ(callTime,'+0:00','-7:00') <= '2010-05-25' 

如果你像我一樣,你可能會開始想,也許它會提高可讀性如果我沒有要求它計算四個不同時間的CONVERT_TZ(callTime,'+0:00','-7:00'),可能還有這個查詢的性能。

所以我試圖創建該表達式的列別名,並與該別名替換進一步匹配的字符串

SELECT id, 
    CONVERT_TZ(callTime,'+0:00','-7:00') as callTimeZoned, 
    DATE_FORMAT(callTimeZoned,'%b %d %Y') as callDate, 
    DATE_FORMAT(callTimeZoned,'%H:%i') as callTimeOfDay, 
    SEC_TO_TIME(callLength) as callLength 
FROM cs_calldata WHERE 
    customerCode='5999999-abc-blahblahblah' AND 
    callTimeZoned >= '2010-04-25' AND 
    callTimeZoned <= '2010-05-25' 

這是當我得知,引用MySQL手冊:

標準SQL不允許在WHERE子句中引用 列別名。這 施加限制,因爲當 WHERE子句評估,該 列值可能還沒有被確定 。

所以,這種做法似乎是死在水中。

如何寫的人與經常性的這樣的表述應該對付它的查詢?

回答

5

您可以在派生表中定義的別名,然後在外部查詢中引用它們:

SELECT callTimeZoned, callLength, 
    DATE_FORMAT(callTimeZoned,'%b %d %Y') as callDate, 
    DATE_FORMAT(callTimeZoned,'%H:%i') as callTimeOfDay 
FROM (
    SELECT 
     CONVERT_TZ(callTime,'+0:00','-7:00') as callTimeZoned, 
     SEC_TO_TIME(callLength) as callLength 
    FROM cs_calldata 
    WHERE customerCode='5999999-abc-blahblahblah' 
) AS d 
WHERE 
    callTimeZoned BETWEEN '2010-04-25' AND '2010-05-25' 
+0

兩個問題: 1)一般:我應該擔心這最終會選擇所有的行在內部查詢中的cs_calldata中,然後使用外部過濾(這看起來效率很低),或者這是否大多數數據庫足夠聰明以創建更好的查詢計劃? 2)具體來說,MySQL是否聰明? :) – 2010-05-26 02:47:12

+1

我不會指望MySQL結合來自內部和外部查詢的行限制,但'EXPLAIN'有助於確認這種或那種方式。至少「customerCode」的條件位於內部查詢中,因此限制了內部查詢中的函數處理的行數。 – 2010-05-26 04:18:50

+0

1)一般不會,你不必擔心。許多RDBMS上的查詢優化器將崩潰/合併所有內容。在應用查詢的外部部分之前,使用內聯視圖不會實現。 2)具體MySQL,我不知道。 – 2010-05-26 04:21:33

1
SELECT id, 
    CONVERT_TZ(callTime,'+0:00','-7:00') as callTimeZoned, 
    DATE_FORMAT(callTimeZoned,'%b %d %Y') as callDate, 
    DATE_FORMAT(callTimeZoned,'%H:%i') as callTimeOfDay, 
    SEC_TO_TIME(callLength) as callLength 
FROM cs_calldata WHERE 
    customerCode='5999999-abc-blahblahblah' having 
    callTimeZoned >= '2010-04-25' AND 
    callTimeZoned <= '2010-05-25' 
相關問題