TSQL选择将多行插入1行,多列最简单的方法

时间:2014-02-02 05:16:57

标签: sql-server tsql cursor pivot-table

我正在使用MS SQL Server 2008 R2,我有一个结果表,我希望从另一个表中的数据填充。

// Results table definition

create table resultsTable
(
  RowId int Identity(1,1) Not Null,

  sid1 int, colA1 int, colB1 int, colC1 int,
  sid2 int, colA2 int, colB2 int, colC2 int,
  sid3 int, colA3 int, colB3 int, colC3 int,
  colX  bit      
)

// Source table definition

create table sourceTable
(
  RowId int Identity(1,1) Not Null ,
  colA int , colB int , colC int , colX bit ,
) 

如果源表有100多行数据,我希望能够使用类似

的内容选择3行
select top 3
       colA,
       colB,
       colC,
       colX
from sourceTable
where Rowid >= @RowIdVariable

其中@RowIdVariable值来自另一个表RowsIdFrom

create table RowIdsFromTable
( 
  id int Identity(1,1) Not Null,
  RowIdFrom int
)

我正在考虑使用游标。

declare MyCursor cursor for
    select RowIdFrom from RowIdsFromTable order by RowIdFrom asc
Open MyCursor 

我知道我的结果在下面的选择语句中看起来如下所示

sid | colA | colB | colC | colX
-------------------------
1     1      2      3      0
2     4      5      6      0
3     7      8      9      1 

通过这些结果,我非常想知道如何将它们插入到我的resultsTable中以便

select *
from resultsTable

应该看起来像下面的结果,并以最有效的方式做到:D

rowId | sid1 | colA1 | colB1 | colC1 | sid2 | colA2 | colB2 | colC2 | sid3 | colA3 | colB3 | colC3 | colX
1       1       1      2       3       2      4       5       6       3      7       8       9       1

其中colX位值属于最后一行,如上例所示,

colA | colB | colC | colX
-------------------------
7      8      9      1 

感谢您的任何指示和帮助:D

140213编辑:

为了提供更多信息或更清楚,我需要在resultsTable中插入返回的行,因为我有另一个表定义了我应该从中选择的所有RowId。该表只包含起点RowId。

如果RowIdsFromTable包含3个值,1,12和20

,则所需的输出可能如下所示
rowId | sid1 | colA1 | colB1 | colC1 | sid2 | colA2 | colB2 | colC2 | sid3 | colA3 | colB3 | colC3 | colX
1       1      1       2       3       2      4       5       6       3      7       8       9       1
2       12     24      9       13      32     13      43      88      14     2       54      23      0
3       20     xx      xx      xx      21     xx      xx      xx      22     xx      xx      xx      1

其中“xx”表示来自sourceTable的整数值。请注意sid升序的顺序。

我附上一个sql小提琴表和一些测试数据:http://sqlfiddle.com/#!3/95fa8/1/0

2 个答案:

答案 0 :(得分:1)

如果您的目标确实是选择有限数量的行来执行此脚本,那么您可以使用下面的解决方案。

WITH Top_3_Rows_CTE AS (
SELECT Top 3 1 AS Artificial_Grouping
    ,RowID
    , colA
    , colB
    , colC
    , colX

FROM sourceTable

WHERE RowID >=2
)

, Row_Numbers_CTE AS (
SELECT ROW_NUMBER() OVER (ORDER BY Artificial_Grouping) AS Row_Number --Pick an order by clause that makes the most sense for your situation
    , Artificial_Grouping
    , RowID
    , ColA
    , ColB
    , ColC
    , ColX

FROM Top_3_Rows_CTE
)

SELECT DISTINCT R2.RowID AS RowID1
    , R2.ColA AS ColA1
    , R2.ColB AS ColB1
    , R2.ColC AS ColC1
    , R2.ColX AS ColX1
    , R3.RowID AS RowID2
    , R3.ColA AS ColA2
    , R3.ColB AS ColB2
    , R3.ColC AS ColC2
    , R3.ColX AS ColX2
    , R4.RowID AS RowID3
    , R4.ColA AS ColA3
    , R4.ColB AS ColB3
    , R4.ColC AS ColC3
    , R4.ColX AS ColX3

FROM Row_Numbers_CTE R1
    LEFT OUTER JOIN Row_Numbers_CTE R2
        ON R2.Row_Number = 1
            AND R1.Artificial_Grouping = R2.Artificial_Grouping
    LEFT OUTER JOIN Row_Numbers_CTE R3
        ON R3.Row_Number = 2
            AND R1.Artificial_Grouping = R3.Artificial_Grouping
    LEFT OUTER JOIN Row_Numbers_CTE R4
        ON R4.Row_Number = 3
            AND R1.Artificial_Grouping = R4.Artificial_Grouping --You would create another join here for each row you want broken out into columns

这应该非常快,因为它开始只选择3行,并且所有处理仅限于包含不超过3行的CTE。您只需为Row_Numbers_CTE添加一个Left Outer Join,以便为要转换为新列的每一行添加。

答案 1 :(得分:1)

你还没有说清楚如何解析X位(从bit中选择一个3),所以我做了一个选择(任意1位获胜,其他为0) )。

以下查询应该使用group by。我们执行以下操作:

  • 使用row_number()为集合
  • 分配连续的行ID
  • 使用模3算术将集合划分为3行组,为组中的每一行分配一个连续的序列号:0,1或2.
  • 通过group by将每个组汇总(展平)为一行,将原始组中的每一行投影到摘要行中的正确列中。

以下是查询:

select t.gid ,
       A1 = sum( case t.seq when 0 then A else null end ) ,
       B1 = sum( case t.seq when 0 then B else null end ) ,
       C1 = sum( case t.seq when 0 then C else null end ) ,
       A2 = sum( case t.seq when 1 then A else null end ) ,
       B2 = sum( case t.seq when 1 then B else null end ) ,
       C2 = sum( case t.seq when 1 then C else null end ) ,
       A3 = sum( case t.seq when 2 then A else null end ) ,
       B3 = sum( case t.seq when 2 then B else null end ) ,
       C3 = sum( case t.seq when 2 then C else null end ) ,
       X  = convert(bit,sign(sum(convert(int,t.X))))
from ( select * ,
              seq = ( row_number() over (order by id) - 1 ) % 3 ,
              gid = ( row_number() over (order by id) - 1 ) / 3
       from dbo.source_table
     ) t
group by t.gid
order by t.gid