【问题标题】:SQL query to get expected resultSQL查询以获得预期结果
【发布时间】:2011-02-18 17:31:06
【问题描述】:

这是我的数据库架构

Table_A
-id 
-status

Table_B
-id

Table_A_has_B
-id
-id_A
-id_B

我需要从 Table_B 中选择所有记录,其中所有关联的 Table_A 记录都有status=1,如果 Table_B 记录没有任何关联的 Table_A 也应该选择。

测试用例:

CREATE TABLE table_a (id int(2),status int(1));
INSERT INTO table_a (id, status)
VALUES (1,1),(2,0),(3,1),(4,1),(5,1);

CREATE TABLE table_b (id int(2));
INSERT INTO table_b (id) VALUES (1),(2),(3),(4);

CREATE TABLE table_a_has_b (id int(2),id_A int(2),id_B int(2));
INSERT INTO table_a_has_b (id, id_A, id_B)
VALUES(1, 1, 1),(2, 2, 1),(3, 3, 1),(4, 4, 2),(5, 5, 2),(6, 3, 4),(7, 4, 4);

查询应该选择:

+----+
|b.id|
+----+
|   2|
|   3|
|   4|
+----+
  • 不应选择 ID 1,因为它的 table_a 记录之一的状态=0
  • 应选择 ID 2 和 4,因为它的所有 table_a 记录的 status=1
  • 应该选择Id 3,因为没有关联的table_a记录,对于相同标准的另一个观点是:应该选择Id 3,因为没有任何table_a记录,其中status=0

【问题讨论】:

  • 首先,中间表中没有 b_id = 3 的条目,为什么它会显示在您的输出中?其次,有一个 b_id = 1 的条目,它与状态 = 1 的 Table_A 行相关联,为什么它没有显示在您的输出中?
  • @Thomas:我刚刚添加了关于预期结果集的解释
  • 好的。直到现在,您尝试实现的目标才有意义。我已经更新了我的答案,为您的难题提供了解决方案。
  • +1 用于提供样本输入和预期输出。

标签: sql mysql join


【解决方案1】:

编辑答案 -

select b.* from table_B b 
left outer join table_A_has_B ab on ab.id_B = b.id
where ab.id in (
    select id from table_A_has_B ab
    where (id_A in (select id from table_A where status = 1 ))
)
or b.id not in 
(select id_B from table_A_Has_B )

旧答案 -

select b.* from table_B b
left outer join table_A a on b.id = a.id
where a.status = 1 or a.id is null

【讨论】:

  • Table_A和Table_B是通过Table_A_has_B链接的,不是直接的。
【解决方案2】:
Select ...
From Table_B As B
    Left Join   (
                Select AB.id_B, A.id, A.status
                From Table_A_has_B As AB
                    Join Table_A As A
                        On A.id = AB.id_A
                Where A.status = 1
                ) As Z
        On Z.id_B = B.id

原帖的这一部分不清楚:if a Table_B record hasn't any associated Table_A also should be selected.

如果您只想要 Table_B 中的行,那么:

Select B.*
From Table_B As B
Where Exists    (
                Select 1
                From Table_A_has_B As AB
                    Join Table_A As A
                        On A.id = AB.id_A
                Where A.status = 1
                    And AB.id_B = B.id
                )

如果您想要来自Table_ B 的行,其中Table_A_has_B 中没有给定id_B 的行,或者如果有行,则它必须与status 为1 的Table_A 项目相关联,然后:

Select B.*
From Table_B As B
Where Exists    (
                Select 1
                From Table_A_has_B As AB
                    Join Table_A As A
                        On A.id = AB.id_A
                Where A.status = 1
                    And AB.id_B = B.id
                )
    Or Not Exists   (
                    Select 1
                    From Table_A_has_B As AB
                    Where AB.id_B = B.id
                    )

如果您想要的是 Table_A 中的行,但只有状态为 1 且所有其他为空的行,那么我提供的第一个查询将是解决方案。为我们提供一些预期的输出结果显然会有很大帮助。

编辑给定的 OP 更新

鉴于您的更新,现在才清楚地表明您实际想要实现的目标,您执行以下操作:

Select B.id
From Table_B As B
Where Not Exists    (
                    Select 1
                    From Table_A_has_B As AB
                        Join Table_A As A
                            On A.id = AB.id_A
                    Where A.status <> 1
                        And AB.id_B = B.id
                    )

【讨论】:

  • 我已经添加了一个测试用例,你的 sql sn-ps 都没有工作。
  • @texai - “不工作”意味着没有产生您期望的输出?
【解决方案3】:

通过改写您的需求语句来选择没有关联 table_A 的 table_B 与状态 1. 我得出以下查询语句:

select distinct b.* 
from table_B b
left outer join table_A_has_B ab on ab.id_B = b.id
left outer join table_A a on a.id = ab.id_A and a.status <> 1
where a.id is null

select b.* 
from table_B b
where not exists (select null from table_A_has_B ab 
inner join table_A a on a.id = ab.id_A and a.status <> 1
where ab.id_B = b.id)

【讨论】:

    猜你喜欢
    • 2021-02-24
    • 2011-01-11
    • 2020-12-28
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    相关资源
    最近更新 更多