我试图随机联接两个表(TableA和TableB)的行,以使TableA中的每一行仅联接到TableB中的一行,而TableB中的每一行联接到TableA中的至少一行。

例如,具有5个不同的行的TableA和具有3个不同的行的TableB的随机联接应产生以下结果:

TableA  TableB
1       3
2       1
3       1
4       2
5       1

但是,有时并非TableB中的所有行都包含在最终结果中; 因此在上面的示例中,TableB中的第2行可能会丢失,因为在第1行或第3行中,第1行或第3行连接了TableA上的第4行。 您可以通过多次执行脚本并检查结果来查看这种情况。 出于某种原因,似乎有必要使用临时表(@Q)来确保返回正确的结果,该结果包含TableA和TableB的所有行。

有人可以解释为什么会这样吗?

另外,有人可以建议什么是获得期望结果的更好方法吗?

我了解,有时由于交叉申请和订购中的某种故障(我尚未确定)而无法返回任何结果,并且我确信有更好的方法可以执行此操作。 我希望这是有道理的。 提前致谢!

    declare @TableA table (
        ID int
        );
    declare @TableB table (
        ID int
        );
    declare @Q table (
        RN int,
        TableAID int,
        TableBID int
        );

    with cte as (
        select
            1 as ID
        union all
        select
            ID + 1
        from cte
        where ID < 5
        )
    insert @TableA (ID)
    select ID from cte;

    with cte as (
        select
            1 as ID
        union all
        select
            ID + 1
        from cte
        where ID < 3
        )
    insert @TableB (ID)
    select ID from cte;

    select * from @TableA;
    select * from @TableB;

    with cte as (
        select
            row_number() over (partition by TableAID order by newid()) as RN,
            TableAID,
            TableBID
        from (
            select
                a.ID as TableAID,
                b.ID as TableBID
            from @TableA as a
            cross apply @TableB as b
            ) as M
        )
    select --All rows from TableB not always included
        TableAID,
        TableBID
    from cte
    where RN in (
        select
            top 1
                iCTE.RN
        from cte as iCTE
        group by iCTE.RN
        having count(distinct iCTE.TableBID) = (
            select count(1) from @TableB
            )
        )
    order by TableAID;

    with cte as (
        select
            row_number() over (partition by TableAID order by newid()) as RN,
            TableAID,
            TableBID
        from (
            select
                a.ID as TableAID,
                b.ID as TableBID
            from @TableA as a
            cross apply @TableB as b
            ) as M
        )
    insert @Q
    select
        RN,
        TableAID,
        TableBID
    from cte;

    select * from @Q;

    select --All rows from both TableA and TableB included
        TableAID,
        TableBID
    from @Q
    where RN in (
        select
            top 1
                iQ.RN
        from @Q as iQ
        group by iQ.RN
        having count(distinct iQ.TableBID) = (
            select count(1) from @TableB
            )
        )
    order by TableAID;

#1楼 票数:1 已采纳

看看这是否能为您提供所需的东西...

DECLARE 
    @CountA INT = (SELECT COUNT(*) FROM @TableA ta),
    @CountB INT = (SELECT COUNT(*) FROM @TableB tb),
    @MinCount INT;

SELECT @MinCount = CASE WHEN @CountA < @CountB THEN @CountA ELSE @CountB END;

WITH 
    cte_A1 AS (
        SELECT 
            *,
            rn = ROW_NUMBER() OVER (ORDER BY NEWID())
        FROM 
            @TableA ta
        ),
    cte_B1 AS (
        SELECT 
            *,
            rn = ROW_NUMBER() OVER (ORDER BY NEWID())
        FROM 
            @TableB tb
        ),
    cte_A2 AS (
        SELECT 
            a1.ID,
            rn = CASE WHEN a1.rn > @MinCount THEN a1.rn - @MinCount ELSE a1.rn end
        FROM 
            cte_A1 a1
        ),
    cte_B2 AS (
        SELECT 
            b1.ID,
            rn = CASE WHEN b1.rn > @MinCount THEN b1.rn - @MinCount ELSE b1.rn end
        FROM 
            cte_B1 b1
        )
SELECT 
    A = a.ID,
    B = b.ID
FROM 
    cte_A2 a
    JOIN cte_B2 b
        ON a.rn = b.rn;

  ask by Erg translate from so

未解决问题?本站智能推荐:

3回复

使用CTE拆分表中的行

我在SQL Server 2008 R2中的表中有以下行 我想做的是基于EntryType分散行(EntryType不变) 并且dt字段将增加(以一个月为间隔),因此输出如下所示: 使用CTE和SQL可以做到吗?
2回复

加入大量CTE表(13,000,000行+)性能问题

我们有一个生产数据库,可以提前几年管理100个分支机构的人员预订,并具有精确的分级。 该系统的一部分是突出差距的报告,即比较分支机构的开放时间和员工预订,以查看是否有任何分支机构在没有预订的情况下打开。 它还同时检查重叠,双重预订等,基本上需要精确的水平精度。 我们这样做的方法
1回复

在SQL Server 2008中使用CTE连接列

我有一张桌子 TABLEX - 此表包含一个名称列,它只是description和table_name列,它实际上是数据库中已存在的表。 X001表包含X1_A, X1_B等列 X002表包含X2_A, X2_B等列 现在,我想以逗号分隔的字符串连接TABLE_NA
2回复

T-SQL:第一行的CTE row_number over()错误结果

我有以下的Calendar表起始于2014-01-01 。 我创建了一个存储过程,并将2014-01-01添加到2020-12-31 。 然后,我想按照以下逻辑检索绝对周编号:当前周-1(上周),是零周(0),我想往后看12周,再往前看6周。 我得到以下结果,第-11周到
3回复

一对多加入

我的数据库中有三个表APPLICATION , APPLICANT和ADDRESS APPLICATION有1行。 APPLICANT可以具有1或2个链接回行APPLICATION经由APPLICATION_ID 。 ADDRESS可以具有1个,2个或3个连接的回行APPLIC
1回复

在CTE或子查询中优化

设定: 我正在尝试使用SQL Server 2008 R2中的OPTIMIZE FOR子句。 我在查询末尾添加了以下内容。 问题: 但是,我收到以下错误。 此变量在查询中的子查询中使用,并且仅在该位置使用。 如果我尝试将OPTIMIZE FOR移到子查询中,则
1回复

从CTE输出插入的行

我有一个CTE,我需要用已插入的行填充该CTE。 我尝试使用临时表。 我不确定如何在CTE中创建临时表并填充CTE。 这是我尝试过的: 下面是该表的架构:
1回复

将参数传递给顶级CTE的内联函数

我需要将参数传递给顶级CTE的内联函数。 有可能这样做吗? 这是我需要的东西。