根据规则3、2、1合并每个表中的Select查询中的三个表

时间:2019-03-09 08:58:57

标签: sql sql-server

按照规则3、2、1从每个表中合并Select查询中的三个表,如下所示:

  • TableA:ID,FieldA,FieldB,FieldC ....
  • TableB:ID,FieldA,FieldB,FieldC ....
  • TableC:ID,FieldA,FieldB,FieldC,....

  • ID:每个表中的自动编号

  • FieldA在所有三个表中都是唯一的。

我正在寻找一个Select查询来合并三个表,如下所示:

  • TableA中按ID排序的前三条记录
  • TableB中按ID排序的前两个记录
  • TableC中的前1条记录,按ID排序

重复此操作,直到从所有三个表中选择所有记录。

如果某个表的记录较少或不符合条件,请忽略该记录并继续其他记录。

我的尝试

我完全通过编程方式做到了这一点,例如SQL Server存储过程中的游标和If条件。

这会造成延迟。

3 个答案:

答案 0 :(得分:0)

这里没有很多信息,但是我假设您可以使用UNION组合多个语句。

SELECT * TableA ORDER BY ID DESC OFFSET 3 ROWS 
UNION
SELECT * TableB ORDER BY ID DESC OFFSET 2 ROWS 
UNION
SELECT * TableC ORDER BY ID DESC OFFSET 1 ROWS 

执行,看看是否可行。

/ AF

答案 1 :(得分:0)

这需要一个公式,该公式从每个表中获取行号,并将其转换为跳过所需值的一系列整数。

在下面的查询中,为了缩短公式,我添加了一些CTE。真正的魔力在UNION中。另外,我为您的控件添加了一个附加字段。随时摆脱它。

WITH A_Aux as (
SELECT 'A' As FromTable, ROW_NUMBER() OVER (ORDER BY ID) AS RowNum, TableA.*
FROM TableA
), B_Aux AS (
SELECT 'B' As FromTable, ROW_NUMBER() OVER (ORDER BY ID) AS RowNum, TableB.*
FROM TableB
), C_Aux AS (
SELECT 'C' As FromTable, ROW_NUMBER() OVER (Order BY ID) AS RowNum, TableC.*
FROM TableC
)
SELECT *
FROM (
    SELECT RowNum+3*FLOOR((RowNum-1)/3) As ColumnForOrder, A_Aux.* FROM A_Aux
    UNION ALL
    SELECT 3+RowNum+4*FLOOR((RowNum-1)/2), B_Aux.* FROM B_Aux
    UNION ALL
    SELECT 6*RowNum, C_Aux.* FROM C_Aux
) T
ORDER BY ColumnForOrder

PS:请注意模式Offset + RowNum + (6-N) * Floor((RowNum-1)/N)将N个记录分组在一起(当然,TableC简化了很多)。

PPS:我没有可用的SQL Server对其进行测试。让我知道是否存在语法错误。

答案 2 :(得分:0)

据我了解,我创建了三个临时表ta,tb和tc。

select * into #ta from (
select 'A' a
union all
select 'A' a
union all
select 'A' a
union all
select 'A' a
union all
select 'A' a
union all
select 'A' a
union all
select 'A' a
) a

select * into #tb from (
select 'B' b
union all
select 'B' 
union all
select 'B' 
union all
select 'B' 
union all
select 'B' 
) b

select * into #tc from (
select 'C' c
union all
select 'C' 
union all
select 'C' 
union all
select 'C' 
union all
select 'C' 
) c

如果表与您的表匹配,则输出看起来像A,A,A,B,B,C,A,A,A,B,B,C,A,B,C,C,C

T-SQL

declare @TAC int = (select count (*) from #ta)      -- Table A Count = 7
declare @TBC int = (select count (*) from #tb)      -- Table B Count = 5

declare @TAR int = @TAC % 3                         -- Table A Reminder = 1  
declare @TBR int = @TBC % 2                         -- Table B Reminder = 1 

declare @TAQ int = (@TAC - @TAR) / 3                -- Table A Quotient = (7 - 1) / 3 = 2, is will passed on NTILE
                                                    -- So we gonna split as two group (111), (222)
declare @TBQ int = (@TBC - @TBR) / 2                -- Table B Quotient = (5 - 1) / 2 = 2, is will passed on NTILE
                                                    -- So we gonna split as two group (11), (22)

select * from (
 select *, NTILE (@TAQ) over ( order by a) FirstOrder, 1 SecondOrder from (
  select top (@TAC - @TAR) * from #ta order by a
 ) ta                                               -- 6 rows are obtained out of 7.
 union all 
 select *, @TAQ + 1, 1 from (
  select top (@TAR) * from #ta order by a desc
 ) ta                                               -- Remaining one row is obtained. Order by desc is must
                                                    -- Here FirstOrder is next value of previous value. 
 union all

 select *, NTILE (@TBQ) over ( order by b), 2  from (
  select top (@TBC - @TBR) * from #tb order by b
 ) tb                                               
 union all 
 select *, @TBQ + 1, 2 from (
  select top (@TBR) * from #tb order by b desc
 ) tb           

 union all 

 select *, ROW_NUMBER () over (order by c), 3 from #tc                                  
) abc order by FirstOrder, SecondOrder  

让我解释一下T-SQL: 在此之前,FYR:NTILERow Number

  1. 获取计数。
  2. 找到将传递给NTILE函数的商。
  3. 按NTILE值和静态排序。

注意:

  1. 我正在使用SQL Server 2017。
  2. 如果T-SQL工作正常,则需要更改order by <yourcolumn>中的列。