左表将表1中的一列连接到表2中的两列

时间:2012-09-08 01:25:49

标签: mysql sql

我有两个表,一个是“电话号码”表,另一个是“电话”表。调用表有两列感兴趣的:原始数字列(c.orig)和终止数字列(c.term)。

我正在尝试编写一个MySQL查询,它将返回调用表中的所有记录,其中 NEITHER c.orig编号或c.term编号存在于数字表中(“n” .nu​​m“数字表中的列。”

这是我的SQL查询:

    SELECT
        c.id, c.date, c.orig, c.term, c.duration
    FROM calls as c
    LEFT JOIN numbers as n ON (n.num = c.orig AND n.num = c.term)
    WHERE
        c.period = '2012-08' AND
        n.num IS NULL
    GROUP BY c.call_id
    ORDER BY c.call_id
    LIMIT 0,300

有什么想法吗?


以下是一些进一步的澄清:

------------------------------
table: numbers
nid     num
1       111-222-3333
2       222-333-4444
3       333-444-5555
------------------------------

------------------------------
table: calls
id      orig            term
1       333-444-5555    999-999-9999
2       999-999-9999    111-222-3333
3       222-333-4444    999-999-9999
4       888-888-8888    999-999-9999
5       777-777-7777    999-999-9999
------------------------------

呼叫ID 1,2和3至少有两个数字(orig或术语)中的一个可以在数字表中找到。

呼叫ID 4和5是这两个电话号码都不在号码表中的情况。那些是我想要找到的记录。记录数字表中没有找到电话号码的记录。

3 个答案:

答案 0 :(得分:1)

你应Jointwice

SELECT
    c.id, c.date, c.orig, c.term, c.duration
FROM calls as c
        LEFT JOIN numbers as n 
            ON (n.num = c.orig)
        LEFT JOIN numbers m
            ON m.num = c.term
WHERE
    c.period = 'date here' AND
    m.num IS NULL
-- GROUP BY c.call_id
ORDER BY c.call_id
LIMIT 0,300

问题,我删除了你的group子句因为我没有看到任何聚合函数。你还想做什么?

更新1

根据您的上述示例,尝试使用此编辑过的。

  

呼叫ID 4和5是这两个电话号码都不是的情况   不在数字表中。这些是我正在尝试的记录   找。记录数字中未找到电话号码的记录

SELECT  a.*
FROM    calls a
        LEFT JOIN numbers b
            ON a.orig = b.num
        LEFT JOIN numbers c
            ON a.term = c.num
WHERE   b.num IS NULL AND
        c.num IS NULL

SQLFiddle Demo

Hpe这是有道理的。

答案 1 :(得分:0)

您应该记住,从逻辑上讲,ON子句中的条件适用于每个单个行,而不是适用于其中的很多行,因此您无法真正拥有任何单个n.num等于 c.origc.term,除非两者是相同的数字(在您的特定情况下会不会义)。

因此,您实际需要检查的是n.num是否等于 c.origc.term。也就是说,只需将AND替换为OR,您就完成了:

SELECT
    c.id, c.date, c.orig, c.term, c.duration
FROM calls as c
LEFT JOIN numbers as n ON (n.num = c.orig OR n.num = c.term)
WHERE
    c.period = '2012-08' AND
    n.num IS NULL
GROUP BY c.call_id
ORDER BY c.call_id
LIMIT 0,300

答案 2 :(得分:0)

这个问题已经使用了EXIST这个词。嗯,这就是存在EXISTS的原因:

SELECT c.id, c.date, c.orig, c.term, c.duration
FROM calls c
WHERE NOT EXISTS ( SELECT *
   FROM numbers a
   WHERE a.num = c.orig
   )
AND NOT EXISTS ( SELECT *
   FROM numbers b
   WHERE b.num = c.term
   );

这两个子查询甚至可以组合成一个:

SELECT c.id, c.date, c.orig, c.term, c.duration
FROM calls c
WHERE NOT EXISTS ( SELECT *
   FROM numbers ab
   WHERE ab.num = c.orig
   OR ab.num = c.term
   );

注意:我省略了期间条件和LIMIT,它们都与实际问题无关。

BTW:“date”是SQL中的保留字。最好不要将它用作列名。