为什么这两个 sql 语句不返回相同的输出?
Why aren't these two sql statements returning same output?
我刚刚开始使用 sql 并且有 objective 来转换它:
select X.persnr
from Pruefung X
where X.persnr in (
select Y.persnr
from pruefung Y
where X.matrikelnr <> Y.matrikelnr)
输出:
进入相同的输出,但使用连接形式。我尝试了下面的方法,但据我所知,我似乎无法获得笛卡尔积的 "rid" 。或者也许我误解了上面的声明它实际上应该做什么。对我来说,上面说 "for each unique matrikelnr display all corresponding persnr"。
select X.persnr
from Pruefung X
join pruefung y on x.persnr=y.persnr
where x.matrikelnr<>y.matrikelnr
输出:一长串(我不想用它来填满整个问题)- 我猜是来自连接的笛卡尔积
这是我正在使用的关系。
编辑:Distinct(除非我在错误的地方使用它)将不起作用,因为 persnr 只显示一次,但那不是 objective。
您的初始查询实际上是:
select 来自 Pruefung 的 persnr 如果不同的 matrikelnr 存在相同的 persnr。
"for each unique matrikelnr display all corresponding persnr"
这是使用聚合实现的:
根据您使用的 DBMS,您可以使用类似(SQL 服务器使用 STRING_AGG,但 MySQL 使用 GROUP_CONCAT)
SELECT matrikelnr,STRING_AGG(matrikelnr,',')
GROUP BY matrikelnr
您无法通过使用联接轻松实现从相关查询(您的第一次尝试)中获得的结果。
编辑:
当没有连接条件(CROSS JOIN)时,连接不会导致 "Cartesian product" 期望。
连接根据连接条件匹配两个集合。您获得更多条目的原因是连接查看连接键 (PERSNR) 并进行匹配。
例如,对于 101,您有 3 个条目。这意味着您将获得 3x3 的结果。
然后过滤掉 X.matrikelnr <> Y.matrikelnr 情况下的结果 如果我们假设 matrikelnr 是唯一的,这意味着该行与自身匹配。所以你将失去 3 个结果,结果为 3x3 - 3 = 6.
如果您想在 SQL 中有所作为,您必须首先定义您期望使用的内容,然后使用适当的工具(在这种情况下相关查询不是连接)
您可以使用 EXISTS
而不是 IN
编写第一个查询,例如:
select X.persnr
from Pruefung X
where exists (
select 1
from pruefung Y
where X.persnr = Y.persnr and X.matrikelnr <> Y.matrikelnr
)
这样很明显这个查询意味着:
return all the persnr
s of the table for which there exists another
row with the same persnr
but different matrikelnr
对于您的示例数据,结果是 table 的所有 persnr
。
虽然你的第二个查询做了一些不同的事情。
它 链接 table 的每一行与相同 table 具有相同 persnr
但不同 matrikelnr
的所有行。
因此,对于 table 的每一行,您将获得与相同 persnr
不同 matrikelnr
的行一样多的行。
例如,对于 persnr = 101
和 matrikelnr = 8532478
的第一行,您将得到 2 行,因为 table 中有 2 行 persnr = 101
和 matrikelnr <> 8532478
。
你是对的。这是笛卡尔积的错。假设第一个 table 中有 persnr 1,1,1,2,2,2,第二个中有 persnr 1,1,1,2,2。您希望返回多少行?
在 pdeuso 代码中它会像这样
Select
...
WHERE persnr in (second table)
-- 6 lines
Select persnr
FROM ...
JOIN ... ON a.persnr = b.persnr
-- 3X3 + 3X2 = 15 lines.
SELECT DISTINCT persnr
FROM ...
JOIN ... ON a.persnr = b.persnr
-- 2 lines (1 and 2)
任你选
我刚刚开始使用 sql 并且有 objective 来转换它:
select X.persnr
from Pruefung X
where X.persnr in (
select Y.persnr
from pruefung Y
where X.matrikelnr <> Y.matrikelnr)
输出:
进入相同的输出,但使用连接形式。我尝试了下面的方法,但据我所知,我似乎无法获得笛卡尔积的 "rid" 。或者也许我误解了上面的声明它实际上应该做什么。对我来说,上面说 "for each unique matrikelnr display all corresponding persnr"。
select X.persnr
from Pruefung X
join pruefung y on x.persnr=y.persnr
where x.matrikelnr<>y.matrikelnr
输出:一长串(我不想用它来填满整个问题)- 我猜是来自连接的笛卡尔积
这是我正在使用的关系。
编辑:Distinct(除非我在错误的地方使用它)将不起作用,因为 persnr 只显示一次,但那不是 objective。
您的初始查询实际上是: select 来自 Pruefung 的 persnr 如果不同的 matrikelnr 存在相同的 persnr。
"for each unique matrikelnr display all corresponding persnr" 这是使用聚合实现的:
根据您使用的 DBMS,您可以使用类似(SQL 服务器使用 STRING_AGG,但 MySQL 使用 GROUP_CONCAT)
SELECT matrikelnr,STRING_AGG(matrikelnr,',')
GROUP BY matrikelnr
您无法通过使用联接轻松实现从相关查询(您的第一次尝试)中获得的结果。
编辑: 当没有连接条件(CROSS JOIN)时,连接不会导致 "Cartesian product" 期望。 连接根据连接条件匹配两个集合。您获得更多条目的原因是连接查看连接键 (PERSNR) 并进行匹配。
例如,对于 101,您有 3 个条目。这意味着您将获得 3x3 的结果。 然后过滤掉 X.matrikelnr <> Y.matrikelnr 情况下的结果 如果我们假设 matrikelnr 是唯一的,这意味着该行与自身匹配。所以你将失去 3 个结果,结果为 3x3 - 3 = 6.
如果您想在 SQL 中有所作为,您必须首先定义您期望使用的内容,然后使用适当的工具(在这种情况下相关查询不是连接)
您可以使用 EXISTS
而不是 IN
编写第一个查询,例如:
select X.persnr
from Pruefung X
where exists (
select 1
from pruefung Y
where X.persnr = Y.persnr and X.matrikelnr <> Y.matrikelnr
)
这样很明显这个查询意味着:
return all the
persnr
s of the table for which there exists another row with the samepersnr
but differentmatrikelnr
对于您的示例数据,结果是 table 的所有 persnr
。
虽然你的第二个查询做了一些不同的事情。
它 链接 table 的每一行与相同 table 具有相同 persnr
但不同 matrikelnr
的所有行。
因此,对于 table 的每一行,您将获得与相同 persnr
不同 matrikelnr
的行一样多的行。
例如,对于 persnr = 101
和 matrikelnr = 8532478
的第一行,您将得到 2 行,因为 table 中有 2 行 persnr = 101
和 matrikelnr <> 8532478
。
你是对的。这是笛卡尔积的错。假设第一个 table 中有 persnr 1,1,1,2,2,2,第二个中有 persnr 1,1,1,2,2。您希望返回多少行? 在 pdeuso 代码中它会像这样
Select
...
WHERE persnr in (second table)
-- 6 lines
Select persnr
FROM ...
JOIN ... ON a.persnr = b.persnr
-- 3X3 + 3X2 = 15 lines.
SELECT DISTINCT persnr
FROM ...
JOIN ... ON a.persnr = b.persnr
-- 2 lines (1 and 2)
任你选