内部连接具有OR条件的两个表

时间:2014-08-13 21:31:49

标签: mysql sql

我想执行以下操作(不起作用):

SELECT COUNT(*) FROM `contestant_flags`
INNER JOIN
    `contestants` ON `contestants`.`id` = `contestant_flags`.`contestant_id`
INNER JOIN
    `teams` ON `teams`.`id` = `contestant_flags`.`team_id`
WHERE
    `contestant_flags`.`flag_id` = 1 AND `contestant_flags`.`call_id` IS NULL AND (`contestants`.`instance_id` = 13 OR `teams`.`instance_id` = 13)

我有一张表contestant_flags,它可以属于单个参赛者或团队(分别为contestant_idteam_id),但不能同时属于两者。参赛者和团队各有一个专栏instance_id,这是我试图过滤的内容。因此,举例来说,我可能有一些参赛者属于参赛者的一些参赛者,其中一些参赛者属于instance_id 13,而一些参赛者属于一个拥有instance_id 13的团队,我希望获得符合其中任何一种条件的参赛队员。

上面的查询不起作用,但考虑到我之后的解释,任何人都可以帮我解决这个问题吗?提前谢谢。

3 个答案:

答案 0 :(得分:1)

让它保持联接。如果你知道其中一个将始终为null,那么coalesce看起来会更好一点。

SELECT COUNT(*) FROM contestant_flags
LEFT JOIN contestants ON contestants.id = contestant_flags.contestant_id
LEFT JOIN teams ON teams.id = contestant_flags.team_id
WHERE contestant_flags.flag_id = 1
AND contestant_flags.call_id IS NULL
AND COALESCE(contestants.instance_id, teams.instance_id) = 13;

答案 1 :(得分:0)

SELECT COUNT(*) 
FROM contestant_flags cf
LEFT JOIN contestants c ON c.id = cf.contestant_id
LEFT JOIN teams t ON t.id = cf.team_id
WHERE
(cf.flag_id = 1) AND 
(cf.call_id IS NULL) AND 
(c.instance_id = 13 OR t.instance_id = 13)

答案 2 :(得分:0)

这是获得结果的一种方法(我认为你在寻找)

SELECT COUNT(*)
  FROM `contestant_flags` f
  LEFT
  JOIN `contestants` c
       ON c.id = f.contestant_id
       AND c.instance_id = 13
  LEFT 
  JOIN `teams` t
       ON t.id = f.team_id
       AND t.instance_id = 13
 WHERE f.flag_id = 1
   AND f.call_id IS NULL
   AND ( c.id IS NOT NULL OR t.id IS NOT NULL )

要在teamscontestants中有匹配的行时返回行,但是至少有一个匹配的行,您可以使用外部联接操作来查找匹配的行,然后在WHERE子句中使用谓词来排除没有匹配的行。

如果instance_id和/或contestants中的teams不唯一,则此查询可能会返回一个大于contestant_flags中匹配的行数的计数。

仅计算来自contesant_flags的行,不计算任何"重复"由JOIN操作生成,您可以将COUNT(*)替换为COUNT(DISTINCT f.id)。 (我假设表contesant_flags有一个名为id的列,保证为非空且唯一;将id替换为任何其他非空唯一列(或表达式)来自contestant_flags

在更一般的情况下,要仅计算来自contestant_flags的行,我们还可以使用EXISTS谓词。

SELECT COUNT(*)
  FROM `contestant_flags` f
 WHERE f.flag_id = 1
   AND f.call_id IS NULL
   AND (  EXISTS 
           ( SELECT 1
               FROM `contestants` c
              WHERE c.id = f.contestant_id
                AND c.instance_id = 13
           ) 
       OR EXISTS
            ( SELECT 1
                FROM `teams` t
               WHERE t.id = f.team_id
                 AND t.instance_id = 13
            )
       )