Sql 与连接逻辑混淆
我发现它如此混乱,以至于我的简单逻辑不起作用 我有一个包含两列ID和代码的数据 1个ID可以链接到多个代码 因此,样本数据如下所示:Sql 与连接逻辑混淆,sql,Sql,我发现它如此混乱,以至于我的简单逻辑不起作用 我有一个包含两列ID和代码的数据 1个ID可以链接到多个代码 因此,样本数据如下所示: ID Code -- ---- a 1 a 2 a 3 b 1 b 3 c 1 c 3 c 4 d 2 d 3 d 4 规则是: 查找代码为1且代码不等于2且代码为3的ID 很明显,a是失败的,b是好的,c是好的,d是失败的 我有下面两种方法,它们都不起作用 你能帮忙吗 非常感谢, 哈利
ID Code
-- ----
a 1
a 2
a 3
b 1
b 3
c 1
c 3
c 4
d 2
d 3
d 4
规则是:
查找代码为1且代码不等于2且代码为3的ID
很明显,a是失败的,b是好的,c是好的,d是失败的
我有下面两种方法,它们都不起作用
你能帮忙吗
非常感谢,
哈利
方法1:
create table mytable (
ID int,
code varchar(255)
);
insert into mytable (ID, code)
values('a','1'),('a','2'),('a','3'),('b','1'),('b','3'),('c','1'),('c','3'),('c','4'),('d','2'),('d','3'),('d','4');
select distinct
ID
from
mytable
where
code = 1
and ID not in (select ID from mytable where code = 2)
and ID in (select ID from mytable where code = 3);
方法2:加入我的表2次
select distinct(T1.ID)
from
(select distinct(mytable1.ID)
from mytable mytable1
join mytable mytable2 on mytable1.ID = mytable2.ID
where mytable1.code = 1
and mytable2.code not in ('2')) as T1
join
(select distinct(mytable3.ID)
from mytable mytable3
where mytable3.code = 3) as T2
on T1.ID = T2.ID
我会在这里使用聚合:
SELECT ID
FROM (SELECT DISTINCT ID, code FROM mytable) t
GROUP BY ID
HAVING
COUNT(CASE WHEN code = 1 THEN 1 END) > 0 AND
COUNT(CASE WHEN code = 2 THEN 1 END) +
COUNT(CASE WHEN code = 3 THEN 1 END) < 2;
HAVING子句确保任何匹配ID的代码为1,并且代码为2或3的情况最多只发生一次,即禁止同时使用代码2和代码3,尽管允许使用其中一个或另一个。欢迎使用S/O。随着时间的推移,阅读其他人和其他反馈,您的帖子会变得更好。您的问题说明了一件事,但查询提供了另一件事 单独部分上的WHERE子句要求代码=1,相应的ID没有代码=2,但除了代码=1外,它还有代码=3
where
code = 1
and ID not in (select ID from mytable where code = 2)
and ID in (select ID from mytable where code = 3);
除了聚合之外,您还可以根据需要使用相同的表和自联接。在本例中,我可以从您的基本查询开始,只查询code=1。然后我会在同一个ID上再次加入,但它也有一个代码3,需要1和3。然后是代码2的第三个左连接,并确保未找到它
select
t1.id
from
MyTable t1
-- now, does it also exist for the same "ID" but also have code = 3
JOIN MyTable t2
on t1.id = t2.id
AND t2.code = 3
-- here, I am explicitly LOOKING for code = 2 for same ID.
-- but by doing a LEFT-JOIN, I only want where it does NOT exist
LEFT JOIN MyTable t3
on t1.id = t3.id
AND t3.code = 2
where
t1.code = 1
-- explicitly making sure the is no match for same ID, code = 2
AND t3.id IS NULL
另一种方法是通过聚合,但得到的计数为1和3,另一种方法是代码=2,但确保计数符合您的需要
select
t1.id
from
MyTable t1
having
sum( case when t1.code = 1 then 1 else 0 end ) > 0
AND sum( case when t1.code = 3 then 1 else 0 end ) > 0
AND sum( case when t1.code = 2 then 1 else 0 end ) = 0
group by
t1.id
在上面的例子中,假设给定ID的多条记录的代码=1,则可能会得到大于1的计数。因此,我只对代码1求和,并且只关心它是否至少有1。对于代码=3且总和至少为1的类似要求。最后,代码之和=2,确保其计数为=0
对OP第二次查询的反馈
在第二次查询中失败的原因在join for code test=3之前的第一部分中
select distinct(T1.ID)
from
(select distinct(mytable1.ID)
from mytable mytable1
join mytable mytable2 on mytable1.ID = mytable2.ID
where mytable1.code = 1
and mytable2.code not in ('2')) as T1
您正在查询table1.code=1的位置,这是确定的,然后您从table1到table2的连接仅在ID上
id code
a 1
a 2
a 3
您的自加入正在返回代码为1、2和3的记录。因此,尽管您可能不想要2,但它仍在引入ID 1和3,这两个ID确实符合条件,因此逻辑上是失败的。这就是为什么在我的第一个示例中,我在同一个id上进行左连接,并显式地使用code=2。。。但是where子句被表3别名ID为NULL的地方显式排除,这意味着它看不到相同ID的记录,代码=2。不能有代码为1和3的行。为什么在我的第二种方法中,ID a是有效的?对于SQL新手来说,有没有更容易消化的方法?但是我不知道为什么我的查询不起作用。我看起来很合乎逻辑。请启发我,因为我的实际工作比这个例子更复杂。感谢你有其他的方法来解决你的问题,但老实说,我认为我的答案是最简单的方法。@ Nick,事实上我的答案检查代码2和3不一起发生。非常感谢你的解释。你能告诉我为什么我的第二种方法会得出错误的答案吗?这让我很生气@Harry,请参阅我答案的修订,以澄清您的收益率不正确的原因。