有时您需要表中的所有行对:其与自身的笛卡尔积。 这可以通过连接来完成。
drop table if exists #a
create table #a (x int)
insert into #a values (1),(2),(3)
select *
from #a a1
join #a a2
on 0 = 0 -- always-true join condition
这给出了九行。
如果我想获得除了行与自身配对以外的对,我可以添加一个需要不同 x 值的连接条件:
select *
from #a a1
join #a a2
on a1.x != a2.x
结果中只给出了六行。 但我假设列 x 是唯一标识符。 假设不是:
delete from #a
insert into #a values (4), (4), (5)
表中有两行保存值 4。它们具有相同的值,但仍然是单独的行,并且 SQL 有时允许您单独处理它们(例如使用
set rowcount 1 update #a set x = 40 where x = 4 set rowcount 0
)。 我仍然想从自连接中获取所有行对,但排除行与自身配对的行对。 所以我想要的输出是(4, 4), (4, 5), (4, 4), (4, 5), (5, 4), (5, 4)
。 输出中仍有六行。
我找到了一个可能的答案,我将发布它。 (当然,有诸如“添加第二列”或“确保列 x 具有唯一值”之类的答案,或者当然“不要尝试制作笛卡尔积”,但我有兴趣了解哪些设施T-SQL 提供。)
select *
from #a a1
join #a a2
on a1.%%physloc%% != a2.%%physloc%%
这个
%%physloc%%
是 Oracle 的 rownum
的松散等效项,并以某种方式给出磁盘上行的标识。 但是,尽管在 Oracle 中看到基于 rownum
的查询相当常见,但在 MSSQL 上我直到现在才遇到过 %%physloc%%
。
根据评论Can %%physloc%% 用作即时查询的行标识符或键吗?即使在执行查询时,行的“位置”也可能会发生变化,因此这不是“可靠的技术。
相关问题ROWNUM作为T-SQL中的伪列等效项?建议使用此解决方案
with t as (select *, row_number() over (order by (select null)) as rownum from #a)
select *
from t a1
join t a2
on a1.rownum != a2.rownum
检查实际的查询计划(诚然在这个小玩具表上)表明这不会引入任何额外的排序步骤,因此应该相当快,尽管可能不如 Oracle 提供的本机
rownum
快。