Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
联接可以在任何地方用来替换SQL中的子查询,这是真的吗_Sql_Join - Fatal编程技术网

联接可以在任何地方用来替换SQL中的子查询,这是真的吗

联接可以在任何地方用来替换SQL中的子查询,这是真的吗,sql,join,Sql,Join,我听到有人说表联接可以在任何地方用来代替子查询。我在查询中测试了它,但发现只有在使用子查询时才检索到相应的数据集。我无法使用联接获得相同的数据集。我不确定我的发现是否正确,因为我是RDBMS的新手,因此没有太多经验。我将尝试绘制我在其中进行实验的数据库的模式(文字): 数据库有两个表: Users(ID,姓名,城市)和友谊(ID,Friend\u ID) 目标:用户表用于存储简单的用户数据,友谊表表示用户之间的友谊。友谊表将这两列都作为外键,引用Users.ID。表之间有多对多关系 问题:我必须

我听到有人说表联接可以在任何地方用来代替子查询。我在查询中测试了它,但发现只有在使用子查询时才检索到相应的数据集。我无法使用联接获得相同的数据集。我不确定我的发现是否正确,因为我是RDBMS的新手,因此没有太多经验。我将尝试绘制我在其中进行实验的数据库的模式(文字):

数据库有两个表:

Users
ID,姓名,城市)和友谊(IDFriend\u ID

目标
:用户表用于存储简单的用户数据,友谊表表示用户之间的友谊。友谊表将这两列都作为外键,引用Users.ID。表之间有多对多关系

问题:我必须检索所有用户的Users.ID和Users.Name,这些用户不是某个用户x的朋友,而是来自同一个城市(很像fb的朋友建议系统)

通过使用子查询,我能够实现这一点。查询如下所示:

SELECT ID, NAME 
FROM USERS AS U
WHERE U.ID NOT IN (SELECT FRIENDS_ID
                   FROM FRIENDSHIP,
                        USERS
                   WHERE USERS.ID = FRIENDSHIP.ID AND USERS.ID = x)
  AND U.ID != x AND CITY LIKE '% A_CITY%';
示例条目:

Users
Id=1 Name=Jon City=Mumbai

Id=2 Name=Doe City=Mumbai

Id=3姓名=阿伦市=孟买

Id=4 Name=Prakash市=德里

Friendship
Id=1个朋友\u Id=2个

Id=2个朋友\u Id=1

Id=2个朋友\u Id=3

Id=3个朋友\u Id=2

我可以通过执行联接在单个查询中获得相同的数据集吗。怎么用?如果我的问题不清楚,请告诉我。谢谢


注意:我通过指定两个表在子查询中使用了内部联接:友谊,用户。省略Users表并从外部使用U会出现错误(但如果不为表用户使用alias,则查询在语法上可以,但此查询的结果包括ID和用户名称,这些用户有多个朋友,包括ID为x的用户。很有趣,但不是问题的主题)

在某些情况下,可以使用联接和子查询来获得类似的结果,但肯定不是全部。例如,此带有子查询的查询无法实现对连接的访问:

SELECT ID, COLUMN1, COUNT(*) FROM MYTABLE
WHERE ID IN (
    SELECT DISTINCT ID FROM MYTABLE
    WHERE COLUMN2 NOT IN (VALUES1, VALUES2)
)
GROUP BY ID;
这只是一个例子,但有很多

相反,如果不连接子查询,则无法通过使用子查询从另一个表获取信息

至于你的例子

SELECT ID, NAME FROM USERS AS U 
WHERE U.ID NOT IN (
    SELECT FRIENDS_ID FROM FRIENDSHIP, USERS 
    WHERE USERS.ID = FRIENDSHIP.ID AND USERS.ID = x) 
AND U.ID != x AND CITY LIKE '% A_CITY%';
这可以理解为:

select ID, NAME from users u
join FRIENDSHIP f        on f.ID = u.ID
where u.ID = x
and u.ID != y
and CITY like '%A_CITY';
我假设把你的第二个x改成了y,这样就不会引起混淆了


当然,如果友谊表中可能有多个结果,您也可能希望使用左连接,即左外部连接。

对于
不在
中,您可以使用
左连接
并检查
是否为空

select u.id, u.name 
from  Users u 
left join Friends f on u.id = f.id and f.friend_id = @person
where u.city like '%city%' and f.friend_id is null and u.id <> @person;
选择u.id、u.name
来自用户u
左键加入朋友f on u.id=f.id和f.friend\u id=@person
其中,u.city(如“%city%”)和f.friend_id为null,u.id@person;
有些情况下,您不能仅使用内部/左/右连接来解决问题,但您的情况不是其中之一

请检查sql FIDLE:


关于您的注意事项:您尝试的操作可以通过
lateral
join或
cross-apply
实现,具体取决于您使用的引擎。

您可以仅使用join重写查询。诀窍是使用内部连接连接到用户表一次,以标识同一城市内的用户,并使用左连接和空检查引用友谊表以标识非朋友

SELECT
     U1.ID,
     U1.Name
FROM
    USERS U1
INNER JOIN
    USERS U2
ON
     U1.CITY = U2.CITY
LEFT JOIN
     FRIENDSHIP F
ON
    U2.ID = F.ID AND
    U1.ID = F.FRIEND_ID
WHERE
     U2.id = X AND
     U1.ID <> U2.id AND
     F.id IS NULL
选择
U1.ID,
U1.名称
从…起
用户U1
内连接
用户U2
在…上
U1.CITY=U2.CITY
左连接
友谊F
在…上
U2.ID=F.ID和
U1.ID=F.FRIEND\u ID
哪里
U2.id=X和
U1.ID U2.ID和
F.id为空

上面的查询不处理用户x的主键位于友谊表的FRIEND_ID列中的情况。我想,因为您的子查询版本不能处理这种情况,可能您为每个友谊创建了2行,或者友谊不是双向的。

我很确定City不是一个参数。@Aheho它与问题无关,但你是对的。我很好奇SQL Server是否会将子查询语句优化为有效的联接。在大多数情况下,特别是在sqlserver/postgre/mysql的较新版本中,它确实会对您的操作方式产生影响吗?@Josh。但是一些旧版本的rdbms可能会提供完全不同的执行计划,我认为这不会有什么帮助,因为查询将返回f.friend_id仅设置为null的行。用户可以有其他朋友。例如,一个用户有两个朋友x(当前用户)和另一个朋友id为y,在加入中有两个条目,并且将返回与此人相关的数据,其中frienship.id=z和friendship.id=y。如果我遗漏了什么,请通过发布答案来澄清。您的第二个查询是错误的,如果此人与来自该城市的两个人是朋友,会发生什么情况?我认为没有y,我必须在内部和外部查询中使用相同的x。此外,您的第一个查询根本不需要子查询和联接:
SELECT ID,COLUMN1,COUNT(*)从MYTABLE中,列2不在(值1,值2)组中,按ID排列vittore,您在原始查询中丢失了DISTINCT。由于我正在运行计数(*),我不想将行排除在总数之外…我想完全排除该ID。您似乎对该查询的工作方式有一些误解。剥离数据库并在其中放入一些数据,然后执行您和我的查询。双向友谊的观点很好。我决定不去追求它,因为它不在原始查询中。F.ID为null,我正在考虑这个条件。如果一个用户有两个或更多的朋友,包括ID为x的用户,该怎么办。它会工作吗?用户X的任何朋友都将被排除在外,因为F.ID为空。你熟悉左连接吗?这是这一战略的关键。