SQL join 得到 3 列中的 2 列的笛卡尔积
SQL join to get the cartesian product of 2 columns out of 3 columns
我有以下 table:
create table #table (
time int,
key char(1),
val int
)
具有以下数据:
insert into #table (time, key, val) values (0,"a",1)
insert into #table (time, key, val) values (0,"b",2)
insert into #table (time, key, val) values (1,"a",10)
insert into #table (time, key, val) values (2,"b",20)
我想想出一个连接将产生以下结果 rows/cols:
0 a 1
0 b 2
1 a 10
1 b 0
2 a 0
2 b 20
这基本上是前 2 列的值的笛卡尔积,当值存在时,它们在第 3 列中的关联值,否则为 0 时为空。
我尝试了几种外连接组合,但 none 似乎有效。
请帮忙。
谢谢。
试试这个:
SELECT DISTINCT t1.time,
t2.key,
IF(
t1.time = t2.time AND t1.key = t2.key AND t1.value = t2.value,
t1.value,
0
) AS value
FROM table_name t1
JOIN table_name t2
ORDER BY t1.time ASC,
t2.key ASC;
Select times.time, keys.key, coalesce(table.val, 0) as val
From (Select distinct time from table) times
cross join
(Select distinct key from table) keys
left outer join table
on times.time = table.time and keys.key = table.key
基本上,您首先构造叉积,然后执行 left outer join。
感谢 simhumileco,这是使其与 Sybase 兼容后的答案。
下面是 table 的创建和填充:
create table #table (
time int,
fet char(1),
val int
)
insert into #table (time, fet, val) values (0,"a",1)
insert into #table (time, fet, val) values (0,"b",2)
insert into #table (time, fet, val) values (1,"a",10)
insert into #table (time, fet, val) values (2,"b",20)
实际解决方案:
Select times.time, fets.fet, coalesce(#table.val, 0) as val
From (Select distinct time from #table) times
JOIN (Select distinct fet from #table) fets on 1=1
left outer join #table
on times.time = #table.time and fets.fet = #table.fet
order by times.time ASC,
fets.fet ASC
产生了:
time fet val
----------- --- -----------
0 a 1
0 b 2
1 a 10
1 b 0
2 a 0
2 b 20
就像我想要的那样。
哇,第一次在SQL问答论坛看到有人专门求笛卡尔积结果!
我的意思是,当人们 回答 想谈论 SQL 的 [=12] 时,SQL 问答论坛中经常提到笛卡尔积结果=],或者在关系代数中简称为 product
(Ted Codd 创造的运算符名称)。
我没有数学背景,直到我开始想写得更好 [=79=] 并且这个词不断出现在答案中(有人记得 Usenet 新闻组吗?)之前我没有听说过笛卡尔积。我听说 SQL 是基于数学集合论,同样是从人们那里 回答 说,"You should look for a set-based approach..." 所以一开始我并没有多想超越,"Cool, I learned a new term today."
后来——也许有点太晚了——我开始研究 SQL 所基于的关系模型 (RM),发现自己质疑自己对笛卡尔积的理解。
这是来自 Wikipedia on the subject 的一行:
for sets A
and B
, the Cartesian product A x B
is the set of all ordered pairs (a, b)
where a
[is an element of] A
and b
[is an element of] B
.
嗯,"ordered pairs"?我对 RM 的了解足够多,知道订购是不合适的。简而言之:在RM中,两个关系之间的操作产生一个关系,一个关系有一个标题,它是一组属性,并且根据定义,一个集合没有顺序;虽然关系首先可以包含有序对属性 ,但有序对不可能作为关系操作的结果具体化。
另一方面,SQL 有很多 left-to-right 排序依赖项(例如 UNION
中的列排序后来用 UNION CORRESPONDING
修复),所以也许笛卡尔product 在 SQL 中有什么意义? SQL 不像 RM 那样严格,但假设两个 table 表达式之间的运算结果是 table 表达式。当运算为CROSS JOIN
时,是不是说结果是所有有序对的集合?
首先,CROSS JOIN
的结果是一个集合吗?好吧,如果涉及的 table 表达式有重复的行,那么结果也会有重复的行,所以严格来说它不会是一个集合。然而,如果我们采取措施确保我们的 table 表达式符合第一范式(实际上我们应该这样做),那么 CROSS JOIN
的结果可以是一个集合。 [我们有一个类似的问题和解决方案,属性名称对于两个 table 表达式都是通用的。]
其次,CROSS JOIN
的结果是一对吗?考虑一个例子:
WITH Suppliers AS
( SELECT * FROM (
VALUES
( 'S1', 'Smith', 'London' ),
( 'S2', 'Jones', 'Paris' )
) AS t ( SID, SNAME, CITY )
),
Parts AS
( SELECT * FROM (
VALUES
( 'S1', 'Nut', 'Red' ),
( 'S2', 'Bolt', 'Green' )
) AS t ( PID, SNAME, COLOR )
)
SELECT *
FROM Suppliers
CROSS JOIN Parts;
结果是四行六列(没有重复的列名)。这些列不以任何方式分组。对我来说,结果中没有任何东西表明我有一对。
第三,CROSS JOIN
的列结果是有序的吗?我们可以切换 tables...
SELECT *
FROM Parts
CROSS JOIN Suppliers;
...而且,这些列很可能会出现在 left-to-right 顺序中,先是 Parts
,然后是 Suppliers
。就个人而言,我不认为这是 'ordered'。 SQL 标准表示 "implementation defined" 对 SELECT *
的影响,这意味着不保证任何固有顺序。我认为 SO 上没有任何知识渊博的人会建议在未明确定义的结果中依赖任何 left-to-right 列排序。
我的结论是 SQL 缺少真正的笛卡尔乘积运算符,并且 CROSS JOIN
只是另一个 SQL 运算,结果是 table 表达式(或类似表达式)。在 SQL 上下文中,我们应该停止使用术语笛卡尔积,而是使用 CROSS JOIN
或简单地使用 product
.
in sql 服务器查询交叉连接给出两列的笛卡尔积(如果两个 table 都是一列 table)。
我有以下 table:
create table #table (
time int,
key char(1),
val int
)
具有以下数据:
insert into #table (time, key, val) values (0,"a",1)
insert into #table (time, key, val) values (0,"b",2)
insert into #table (time, key, val) values (1,"a",10)
insert into #table (time, key, val) values (2,"b",20)
我想想出一个连接将产生以下结果 rows/cols:
0 a 1
0 b 2
1 a 10
1 b 0
2 a 0
2 b 20
这基本上是前 2 列的值的笛卡尔积,当值存在时,它们在第 3 列中的关联值,否则为 0 时为空。
我尝试了几种外连接组合,但 none 似乎有效。
请帮忙。
谢谢。
试试这个:
SELECT DISTINCT t1.time,
t2.key,
IF(
t1.time = t2.time AND t1.key = t2.key AND t1.value = t2.value,
t1.value,
0
) AS value
FROM table_name t1
JOIN table_name t2
ORDER BY t1.time ASC,
t2.key ASC;
Select times.time, keys.key, coalesce(table.val, 0) as val
From (Select distinct time from table) times
cross join
(Select distinct key from table) keys
left outer join table
on times.time = table.time and keys.key = table.key
基本上,您首先构造叉积,然后执行 left outer join。
感谢 simhumileco,这是使其与 Sybase 兼容后的答案。
下面是 table 的创建和填充:
create table #table (
time int,
fet char(1),
val int
)
insert into #table (time, fet, val) values (0,"a",1)
insert into #table (time, fet, val) values (0,"b",2)
insert into #table (time, fet, val) values (1,"a",10)
insert into #table (time, fet, val) values (2,"b",20)
实际解决方案:
Select times.time, fets.fet, coalesce(#table.val, 0) as val
From (Select distinct time from #table) times
JOIN (Select distinct fet from #table) fets on 1=1
left outer join #table
on times.time = #table.time and fets.fet = #table.fet
order by times.time ASC,
fets.fet ASC
产生了:
time fet val
----------- --- -----------
0 a 1
0 b 2
1 a 10
1 b 0
2 a 0
2 b 20
就像我想要的那样。
哇,第一次在SQL问答论坛看到有人专门求笛卡尔积结果!
我的意思是,当人们 回答 想谈论 SQL 的 [=12] 时,SQL 问答论坛中经常提到笛卡尔积结果=],或者在关系代数中简称为 product
(Ted Codd 创造的运算符名称)。
我没有数学背景,直到我开始想写得更好 [=79=] 并且这个词不断出现在答案中(有人记得 Usenet 新闻组吗?)之前我没有听说过笛卡尔积。我听说 SQL 是基于数学集合论,同样是从人们那里 回答 说,"You should look for a set-based approach..." 所以一开始我并没有多想超越,"Cool, I learned a new term today."
后来——也许有点太晚了——我开始研究 SQL 所基于的关系模型 (RM),发现自己质疑自己对笛卡尔积的理解。
这是来自 Wikipedia on the subject 的一行:
for sets
A
andB
, the Cartesian productA x B
is the set of all ordered pairs(a, b)
wherea
[is an element of]A
andb
[is an element of]B
.
嗯,"ordered pairs"?我对 RM 的了解足够多,知道订购是不合适的。简而言之:在RM中,两个关系之间的操作产生一个关系,一个关系有一个标题,它是一组属性,并且根据定义,一个集合没有顺序;虽然关系首先可以包含有序对属性 ,但有序对不可能作为关系操作的结果具体化。
另一方面,SQL 有很多 left-to-right 排序依赖项(例如 UNION
中的列排序后来用 UNION CORRESPONDING
修复),所以也许笛卡尔product 在 SQL 中有什么意义? SQL 不像 RM 那样严格,但假设两个 table 表达式之间的运算结果是 table 表达式。当运算为CROSS JOIN
时,是不是说结果是所有有序对的集合?
首先,CROSS JOIN
的结果是一个集合吗?好吧,如果涉及的 table 表达式有重复的行,那么结果也会有重复的行,所以严格来说它不会是一个集合。然而,如果我们采取措施确保我们的 table 表达式符合第一范式(实际上我们应该这样做),那么 CROSS JOIN
的结果可以是一个集合。 [我们有一个类似的问题和解决方案,属性名称对于两个 table 表达式都是通用的。]
其次,CROSS JOIN
的结果是一对吗?考虑一个例子:
WITH Suppliers AS
( SELECT * FROM (
VALUES
( 'S1', 'Smith', 'London' ),
( 'S2', 'Jones', 'Paris' )
) AS t ( SID, SNAME, CITY )
),
Parts AS
( SELECT * FROM (
VALUES
( 'S1', 'Nut', 'Red' ),
( 'S2', 'Bolt', 'Green' )
) AS t ( PID, SNAME, COLOR )
)
SELECT *
FROM Suppliers
CROSS JOIN Parts;
结果是四行六列(没有重复的列名)。这些列不以任何方式分组。对我来说,结果中没有任何东西表明我有一对。
第三,CROSS JOIN
的列结果是有序的吗?我们可以切换 tables...
SELECT *
FROM Parts
CROSS JOIN Suppliers;
...而且,这些列很可能会出现在 left-to-right 顺序中,先是 Parts
,然后是 Suppliers
。就个人而言,我不认为这是 'ordered'。 SQL 标准表示 "implementation defined" 对 SELECT *
的影响,这意味着不保证任何固有顺序。我认为 SO 上没有任何知识渊博的人会建议在未明确定义的结果中依赖任何 left-to-right 列排序。
我的结论是 SQL 缺少真正的笛卡尔乘积运算符,并且 CROSS JOIN
只是另一个 SQL 运算,结果是 table 表达式(或类似表达式)。在 SQL 上下文中,我们应该停止使用术语笛卡尔积,而是使用 CROSS JOIN
或简单地使用 product
.
in sql 服务器查询交叉连接给出两列的笛卡尔积(如果两个 table 都是一列 table)。