MS SQL Server中如何按行对齐合并两张表(非Concatenate、JOIN/CROSS JOIN)
按行对齐合并两张表(无需关联条件)
嘿,我完全懂你的困扰!你想要的不是字符串拼接,也不是常规的SQL JOIN操作(不管是带关联条件的还是CROSS JOIN那种笛卡尔积),而是把两张已经按行严格对齐的表,直接按行号把对应行的字段拼在一起——第1行配第1行,第2行配第2行,对吧?
这种操作的核心思路是:给两张表都生成一个行号标记,然后通过这个行号来做等值连接,就能实现逐行合并的效果。下面分不同SQL方言给出实现方案:
支持窗口函数的数据库(MySQL 8.0+/PostgreSQL/SQL Server 2012+)
这类数据库可以直接用ROW_NUMBER()窗口函数生成行号,再关联:
SELECT t1.name, t1.city, t2.phone, t2.email FROM ( -- 给表1添加行号 SELECT name, city, ROW_NUMBER() OVER () AS row_num FROM table1 ) t1 JOIN ( -- 给表2添加行号 SELECT phone, email, ROW_NUMBER() OVER () AS row_num FROM table2 ) t2 ON t1.row_num = t2.row_num;
注意:如果你的表没有明确的排序字段,
ROW_NUMBER() OVER ()在部分数据库中可能不会严格保证物理行顺序。如果需要绝对对齐,建议在OVER()里加上一个能确定顺序的字段(比如主键),例如:ROW_NUMBER() OVER (ORDER BY id) AS row_num。
旧版本MySQL(无窗口函数)
可以用用户自定义变量来生成行号:
SELECT t1.name, t1.city, t2.phone, t2.email FROM ( SELECT name, city, @row1 := @row1 + 1 AS row_num FROM table1, (SELECT @row1 := 0) AS init_var ) t1 JOIN ( SELECT phone, email, @row2 := @row2 + 1 AS row_num FROM table2, (SELECT @row2 := 0) AS init_var ) t2 ON t1.row_num = t2.row_num;
这种方式完全避开了容易引发误解的JOIN语义歧义(别人不会以为你是基于业务字段关联),也不会生成笛卡尔积,完美匹配你“按行对齐合并”的需求。
内容的提问来源于stack exchange,提问作者Mike Williamson
相关产品推荐
相关产品推荐

