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 创造的运算符名称)。

我没有数学背景,直到我开始想写得更好 [=7​​9=] 并且这个词不断出现在答案中(有人记得 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)。