2014-01-21 103 views
2
SELECT * 
FROM (
    `lecture` AS l 
) 
LEFT JOIN `professor` AS p ON `p`.`professor_id` = `l`.`professor_id` 
WHERE `lecture_sem` = '20141' 
AND (
    lecture_name LIKE '%KEYWORD%' 
    OR lecture_code LIKE '%KEYWORD%' 
    OR p.professor_name LIKE '%KEYWORD%' 
) 
AND (
    SELECT COUNT(DISTINCT s1.yoil, s1.start_time, s1.end_time) 
    FROM schedule AS s1 
    INNER JOIN schedule AS s2 ON (s1.lecture_id 
    IN (
     SELECT lecture_id 
     FROM timeitem 
     WHERE timetable_id =890 
    ) 
AND s2.yoil = s1.yoil 
AND (
    (
    s1.start_time <= s2.start_time 
    AND s2.end_time <= s1.end_time 
    )) 
    AND s2.lecture_id = lecture_id # <-- HERE 
    ) 
) >0 
LIMIT 0 , 30 

我想去的地方像這樣柱使用方法:子查詢:在條款不明確

s2.lecture_id = lecture_id 

,或者

s2.lecture_id = l.lecture_id 

所以我想在子查詢中使用父列,但是會出現誤差:

Column 'lecture_id' in on clause is ambiguous 

我GOOGLE了這個PR很多答案(「關於子句是不明確的」),他們說我應該替換這個查詢來加入兩個查詢。但我不知道如何轉換此查詢。

+0

看看這是相關還是一個[重複](http://stackoverflow.com/questions/2788326/mysql-user-id-in-where-clause-is-ambiguous-problem)。 – user2989408

回答

2

我相信下面的等效查詢,但我沒有測試它。

該技巧是將相關子查詢作爲派生表移動到FROM子句中,以便它只運行一次,爲每個lecture_id(因此爲GROUP BY)生成一個結果。

我也分析了時間表的子查詢,我相信它可以重寫爲JOIN。

我懷疑加入教授可能是一個內部加入 - 你怎麼能沒有教授講座?

SELECT l.*, p.* 
FROM lecture AS l 
INNER JOIN professor AS p ON p.professor_id = l.professor_id 
INNER JOIN (
    SELECT s2.lecture_id, COUNT(DISTINCT s1.yoil, s1.start_time, s1.end_time) AS count 
    FROM schedule AS s1 
    INNER JOIN schedule AS s2 ON s2.yoil = s1.yoil 
     AND s1.start_time <= s2.start_time AND s2.end_time <= s1.end_time 
    INNER JOIN timeitem AS t ON s1.lecture_id = t.lecture_id 
    WHERE t.timetable_id = 890 
    GROUP BY s2.lecture_id 
) AS c ON l.lecture_id = c.lecture_id 
WHERE l.lecture_sem = '20141' 
    AND c.count > 0 
    AND (
     l.lecture_name LIKE '%KEYWORD%' 
     OR l.lecture_code LIKE '%KEYWORD%' 
     OR p.professor_name LIKE '%KEYWORD%' 
    ) 
LIMIT 0 , 30 

無論如何,即使查詢不完美,它也會演示如何重構它以避免相關的子查詢。

0

您在代碼中標識的行不是ON子句。

相反,我認爲錯誤是指以下部分。

AND (
    SELECT COUNT(DISTINCT s1.yoil, s1.start_time, s1.end_time) 
    FROM schedule AS s1 
    INNER JOIN schedule AS s2 ON (s1.lecture_id 
    IN (
     # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 
     SELECT lecture_id # <---- HERE 
     # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
     FROM timeitem 
     WHERE timetable_id =890 
    ) 

您可以通過爲timeitem表創建一個別名,並以這個前綴前綴列解決這個問題:

IN (
    SELECT ti.lecture_id 
    FROM timeitem as ti 
    WHERE ti.timetable_id =890 
) 

但正如比爾Karwin在他的回答中指出,你有其他的邏輯問題需要加以解決。