使用动态sql旋转两列

时间:2017-10-20 17:50:58

标签: sql sql-server-2005

我正在尝试将两个cols转到行

NO Code_01 Amount_01 Code_02 Amount_02 Code_03 Amount_03 Code_04 Amount_04
1  61      1714.00   23      95.79     80      31.00     61      45.00
2  61      1714.00   23      95.79     - - - - 
...

我想动态地将Code和Amount cols旋转到下面,并为列名添加后缀

DECLARE @cols NVARCHAR(MAX)
    ,@sql NVARCHAR(MAX)

SET @cols = STUFF((
            SELECT DISTINCT ',' + QUOTENAME(CODE)
            FROM Table1
            ORDER BY 1
            FOR XML PATH('')
                ,TYPE
            ).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET @sql = 'SELECT NO,  ' + @cols + '
              FROM
            (
              SELECT NO
                FROM Table1
            ) s
            PIVOT
            (
              MAX(Amount) FOR Code IN (' + @cols + ')
            ) p'

--print(@sql)

EXECUTE(@sql)

我开始做一个专栏但遇到错误......对此有任何帮助吗?

Sub OVR_Office_Listing()
  Dim i As String

'MsgBox prompt:="1st 6 Months of Reports?", Title:="Referral Workbook - Data Entry"
i = MsgBox("Continue to OVR Office Directory?", vbYesNo, " Referral Workbook - Data Entry")

If Not i = vbYes Then Exit Sub

'First message shows in the body of the box, message 2 shows at the top of the box.
Do
    MyValue = Application.InputBox("Only Click Ok or Cancel after your Selection!!!!!!!" & vbCrLf & _
                           "1 = OVR Office Directory" & vbCrLf & _
                           "2 = BBVS (Bureau of Blindness & Visual Services)Office Directory", "Walk In Training Data Entry")
    ' Sub messaage box exit.
    If MyValue = False Then
        Exit Sub
    ElseIf (MyValue = 1) Or (MyValue = 2) Then
        Exit Do
    Else
        MsgBox "You have not made a valid entry.  Please try again.", vbInformation, "Referral Workbook - Data Entry"
    End If
Loop    'Code to Execute When Condition = value_1

Select Case MyValue
    Case 1
           ' The message below only shows when you are on the active sheet.
                    MsgBox "You are already on OVR Office Directory!", vbInformation, "Referral Workbook - Data Entry"
    Case 2
                Dim ie As Object
Set ie = CreateObject("INTERNETEXPLORER.APPLICATION")
ie.NAVIGATE "http://www.dli.pa.gov/Individuals/Disability-Services/bbvs/Pages/BBVS-Office-Directory.aspx"
ie.Visible = True
'End Select
                'End If
    'Code to Execute When Condition = value_2
    Case 3

           ' The message below only shows when you are on the active sheet.
                    MsgBox "You are already on Bureau of Blindness & Visual Services Office Directory!", vbInformation, "Referral Workbook - Data Entry"
                'Else
                  Dim ie2 As Object
Set ie = CreateObject("INTERNETEXPLORER.APPLICATION")
ie2.NAVIGATE "http://www.dli.pa.gov/individuals/disability-services/ovr/pages/OVR-office-directory.aspx"
ie2.Visible = True
End Select

2 个答案:

答案 0 :(得分:3)

使用动态sql生成条件聚合语句,以max() No(由declare @cols nvarchar(max); declare @sql nvarchar(max); select @cols = stuff(( select distinct char(10)+' , ' + quotename('Code_'+rn)+' = max(case when rn = '+rn+' then Code end)' + char(10)+' , ' + quotename('Amount_'+rn)+' = max(case when rn = '+rn+' then Amount end)' from ( select No, Code , rn = convert(varchar(10),row_number() over (partition by No order by Code)) from Table1 ) s order by 1 for xml path (''), type).value('.','nvarchar(max)') ,1,0,''); select @sql =' select No '+@cols+' from ( select No, Code, Amount , rn = row_number() over (partition by No order by Code) from Table1 ) sub group by No'; select @sql; exec(@sql); 分区)而不是多个支点获取select No , [Code_1] = max(case when rn = 1 then Code end) , [Amount_1] = max(case when rn = 1 then Amount end) , [Code_2] = max(case when rn = 2 then Code end) , [Amount_2] = max(case when rn = 2 then Amount end) , [Code_3] = max(case when rn = 3 then Code end) , [Amount_3] = max(case when rn = 3 then Amount end) , [Code_4] = max(case when rn = 4 then Code end) , [Amount_4] = max(case when rn = 4 then Amount end) , [Code_5] = max(case when rn = 5 then Code end) , [Amount_5] = max(case when rn = 5 then Amount end) from ( select No, Code, Amount , rn = row_number() over (partition by No order by Code) from Table1 ) sub group by No

+----+--------+----------+--------+----------+--------+----------+--------+----------+--------+----------+
| No | Code_1 | Amount_1 | Code_2 | Amount_2 | Code_3 | Amount_3 | Code_4 | Amount_4 | Code_5 | Amount_5 |
+----+--------+----------+--------+----------+--------+----------+--------+----------+--------+----------+
|  1 |     23 | 95.79    | 61     | 45.00    | 61     | 1714.00  | 80     | 31.00    | NULL   | NULL     |
|  2 |     23 | 95.79    | 61     | 1714.00  | NULL   | NULL     | NULL   | NULL     | NULL   | NULL     |
|  3 |     80 | 31.00    | NULL   | NULL     | NULL   | NULL     | NULL   | NULL     | NULL   | NULL     |
|  4 |     23 | 95.79    | 61     | 45.00    | 61     | 45.00    | 61     | 1714.00  | 80     | 31.00    |
+----+--------+----------+--------+----------+--------+----------+--------+----------+--------+----------+

rextester演示:row_number()

代码生成:

{{1}}

结果:

{{1}}

答案 1 :(得分:2)

您可以像这样动态创建PIVOT查询。

DECLARE @ColumnNames NVARCHAR(MAX) =''
SELECT  @ColumnNames = @ColumnNames + ', ' + QUOTENAME ( 'Code_' +  RN ) + ', ' + QUOTENAME ( 'Amount_' + RN  )  
FROM (SELECT DISTINCT RN = RIGHT('0' + CONVERT(varchar, ROW_NUMBER() OVER(PARTITION BY [NO] ORDER BY [NO]) ),2) FROM Table1 ) AS T
SET @ColumnNames = STUFF(@ColumnNames,1,1,'')


DECLARE @SqlText NVARCHAR(MAX)
SET @SqlText  = 'SELECT * FROM 
                    (SELECT [NO], ''Code_'' + RIGHT(''0'' + CONVERT(varchar, ROW_NUMBER() OVER(PARTITION BY [NO] ORDER BY [NO]) ),2) Col, CONVERT(VARCHAR,Code) Value FROM Table1
                       UNION ALL
                    SELECT  [NO], ''Amount_'' + RIGHT(''0'' + CONVERT(varchar, ROW_NUMBER() OVER(PARTITION BY [NO] ORDER BY [NO]) ),2) Col, CONVERT(VARCHAR,Amount) Value FROM Table1 ) SRC
                    PIVOT (MAX(Value) FOR Col IN (' + @ColumnNames + ') ) PVT'

print @SqlText
EXEC sp_executesql @SqlText

制作查询:

SELECT * FROM 
(SELECT [NO], 'Code_' + RIGHT('0' + CONVERT(varchar, ROW_NUMBER() OVER(PARTITION BY [NO] ORDER BY [NO]) ),2) Col, CONVERT(VARCHAR,Code) Value FROM Table1
    UNION ALL
SELECT  [NO], 'Amount_' + RIGHT('0' + CONVERT(varchar, ROW_NUMBER() OVER(PARTITION BY [NO] ORDER BY [NO]) ),2) Col, CONVERT(VARCHAR,Amount) Value FROM Table1 ) SRC
PIVOT (MAX(Value) FOR Col IN ( [Code_01], [Amount_01], [Code_02], [Amount_02], [Code_03], [Amount_03], [Code_04], [Amount_04], [Code_05], [Amount_05]) ) PVT

结果:

NO  Code_01  Amount_01  Code_02  Amount_02  Code_03  Amount_03  Code_04  Amount_04  Code_05  Amount_05 
--- -------  ---------  -------  ---------  -------  ---------  -------  ---------  -------  ---------
1   61       1714.00    23       95.79      80       31.00      61       45.00      NULL     NULL
2   61       1714.00    23       95.79      NULL     NULL       NULL     NULL       NULL     NULL
3   80       31.00      NULL     NULL       NULL     NULL       NULL     NULL       NULL     NULL
4   61       45.00      61       1714.00    23       95.79      80       31.00      61       45.00