我有两个SQL Server表:CHANNELS
& SUBSCRIBERS
,我希望从CHANNELS
获取SUBSCRIBERS
中某些情况下不存在的行。
我尝试了INNER
和OUTER(LEFT) JOIN
,但它对我没用,他们都给了我相同的答案,这不是我想要的。
表格是这样的:
CHANNELS 表:
CREATE TABLE CHANNELS
(
ChanID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1) PRIMARY KEY,
name varchar(30) NOT NULL,
type varchar(10) NOT NULL,
description varchar(500) NOT NULL,
nickname varchar(20) NOT NULL
REFERENCES USERS(nickname),
subscribersnum int NOT NULL
)
订阅者表:
CREATE TABLE SUBSCRIBERS
(
nickname varchar(20) NOT NULL REFERENCES USERS(nickname),
ChanID int NOT NULL REFERENCES CHANNELS(ChanID)
)
外键nickname
取自其他名为USERS
我们在 CHANNELS 中说我们有以下几行:
CHanID | type | name | description | (createdby) | subscribersnum
| | | | nickname |
-------------------------------------------------------------------------
1 public first hi Matty 3
2 public second hii Rose 2
3 private third hiii Matty 2
4 public forth hiiii Lucy 5
并且SUBSCRIBERS
我们有:
nickname | ChanID
------------------------
Jonny 1
Matty 3
Jonny 4
Rose 3
Rose 2
我想选择所有公共频道'具有昵称" Jonny"的用户的ID和名称尚未订阅,所以在上面的示例中,我希望查询返回两行:
ChanId | name
-----------------
2 second
我所做的查询是:
SELECT
CHANNELS.ChanID
FROM
CHANNELS
LEFT JOIN
SUBSCRIBERS ON (CHANNELS.type = 'public'
AND SUBSCRIBERS.nickname = 'Jonny'
AND CHANNELS.ChanID != SUBSCRIBERS.ChanID);
SELECT
CHANNELS.ChanID
FROM
CHANNELS
INNER JOIN
SUBSCRIBERS ON (CHANNELS.type = 'public'
AND SUBSCRIBERS.nickname = 'Jonny'
AND CHANNELS.ChanID != SUBSCRIBERS.ChanID);
但他们并没有做我需要的事。
有什么建议吗?
由于
答案 0 :(得分:2)
如果您想知道记录是否存在,请使用[NOT] EXISTS
或[NOT] IN
。您需要表channels
中的数据,因此请从此表中选择,并在WHERE
子句中包含您的条件。
select chanid, name
from channels
where type = 'public'
and chanid not in (select chanid from subscribers where nickname = 'Jonny');
答案 1 :(得分:1)
您似乎将连接条件与where条件混淆。 此外,您的预期结果中存在错误,第三个频道不应根据您之前的条件出现,即只需要PUBLIC类型。
WITH CTE AS
(
SELECT CASE
WHEN Address_line_1 = '' THEN Address_line_2
ELSE Address_line_1
END Address_line
FROM @tab
)
SELECT *,
CASE
WHEN Address_line LIKE '%|%'
THEN RIGHT(Address_line,CHARINDEX('|',REVERSE(Address_line))-1) +
' ' + LEFT(Address_line,CHARINDEX('|',Address_line)-1)
ELSE Address_line
END Result
FROM CTE;
这应该可以解决问题。
答案 2 :(得分:1)
您一直在尝试应用反连接模式,当您遇到直接NOT EXISTS
或{{1}的性能问题时,通常会使用反连接模式 (当DBMS优化器没有充分处理这些时)会发生这种情况。
我已经向您展示了如何编写直接查询。谢谢你的接受: - )
为了完整起见,我在这里告诉你如何构建反连接:反连接因此你外连接另一个表,但是然后解除where子句中的所有匹配,从而保持不匹配。这可能会导致较大的中间结果,但通常执行速度仍然很快,因为加入是DBMS可以做得最好的(特别是那些不能很好地优化的年轻DBMS)。
NOT IN
答案 3 :(得分:0)
为未经测试且绝对不是最高效解决方案而冒险使用brickbats,但在考虑了这一点后,我认为最好的方法是获得所有组合,然后看看哪个用户列表中没有一个:
select distinct a.nickname,b.chanid
from subscribers a
cross join
(select chanid
from channels
where type='public') b
left outer join subscribers c
on a.nickname=c.nickname
and b.chanid=c.chanid
where c.chanid is null
交叉连接为您提供所有可能的订阅者组合。那么,诀窍在于查看订户表中是否存在这些组合中的每一个。这允许您在右侧使用外连接并测试null。同样,也许不是完美或理想的解决方案,但我认为它可以为您提供经验所需。再次,没有测试,但我相信这个想法是可行的。