2013-07-30 40 views
0

我在查詢表1中的日期列基於子查詢。 where子句中的子查詢1從外鍵引用表中獲取描述,子查詢2通過其他條件獲取數據。可能替代一堆子查詢

所以我的問題是,我有什麼替代方案使這個查詢更好?

SELECT count(*) AS non_saturday 
FROM t_booking 
WHERE p_id IN (
     SELECT p_id 
     FROM p_detail 
     WHERE p_name IN ('A','B') 
     ) 
    AND date_format(p_date, '%Y%m%d') IN (
     SELECT DISTINCT CONCAT (
       gregorian_ccyy 
       ,gregorian_month 
       ,gregorian_day 
       ) 
     FROM m_gregorian_calendar1 c 
     WHERE c.day_of_the_week = (
       SELECT day_id 
       FROM m_gregorian_day 
       WHERE day_name = 'SATURDAY' 
       ) 
      AND c.gregorian_ccyy = '2012' 
      AND c.gregorian_month = '10' 
     ) 
+1

一個建議是查看使用JOIN而不是子查詢。 – Taryn

+1

正如@bluefeet提到的那樣,你可以簡單地加入你的三個表,而不是使用子查詢。但是,您不希望將該date_format/concatenation業務用於連接表,因爲這不允許使用索引。 –

+0

我忘了提及我添加2012年和10月硬編碼,因爲這是來自一個窗體。正如所建議的,我可以使用內部連接,但我認爲這會使查詢不易讀。 –

回答

2

這不是可能直接回答你的問題,但如果以「星期六」你的意思是直週六(而不是某些日曆的日期和星期幾間不同的映射),它在我看來,你可以簡單地運行

SELECT count(*) AS non_saturday 
    FROM t_booking 
    JOIN p_detail ON (t_booking.p_id = p_detail.p_id AND p_name IN ('A','B')) 
    WHERE 
     DAYOFWEEK(p_date) = 7 
     AND MONTH(p_date) = 10 
     AND YEAR (p_date) = 2012 

或對p_date領域更好地利用索引,

WHERE p_date BETWEEN "2012-10-01" AND "2012-10-31" 

(但使用BETWEEN在日期字段中,也檢查this answer)。

+0

這真棒。不知道Dayofweek函數。我可以直接在這裏使用它,而不是從日曆表中過濾,該日曆表的day_of_week列沿着函數的行。有一件事我不明白的是爲什麼條件在條款? –

+0

這是因爲'p_detail'表具有基於'p_name'的'WHERE'條件,所以我不能直接創建'JOIN'並且必須添加相應的'WHERE'。你可能想看看一些使用'JOIN'的教程(也可能是索引)。 – LSerni