2014-01-21 67 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在他的回答中指出,你有其他的逻辑问题需要加以解决。