子查询:on子句不明确

时间:2014-01-21 16:43:13

标签: mysql sql subquery

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搜索了关于这个问题的许多答案(“on clause is ambiguous”),他们说我应该将此查询替换为加入两个查询。但我不知道如何转换此查询。

2 个答案:

答案 0 :(得分: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

无论如何,即使查询不完美,它也会演示如何重构它以避免相关的子查询。

答案 1 :(得分: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
)

但正如Bill Karwin在答案中指出的那样,你还有其他需要解决的逻辑问题。