0

好吧,我真的尝试使用我昨天在@AaronBertrand 的问答中学到的东西来解决类似类型的问题。我在 Microsoft SQL Server 2008 R2 中使用

我的数据如下所示:

SalesPersonID TransDate   Order     DateTotal
1108          8/2/2013    231.95    7713.8
1108          8/2/2013    5805.15   7713.8
1108          8/2/2013    1676.70   7713.8
1108          8/3/2013    159.95    3635.35
1108          8/3/2013    468.90    3635.35
1108          8/3/2013    1160.85   3635.35
1108          8/3/2013    209.95    3635.35
1108          8/3/2013    1161.85   3635.35
1108          8/3/2013    473.85    3635.35
1108          8/4/2013    149.98    3151.68
1108          8/4/2013    793.95    3151.68
1108          8/4/2013    55.00     3151.68
1108          8/4/2013    198.95    3151.68
1108          8/4/2013    398.00    3151.68
1108          8/4/2013    1255.85   3151.68
1108          8/4/2013    299.95    3151.68
1108          8/9/2013    223.95    1413.8
1108          8/9/2013    59.95     1413.8
1108          8/9/2013    1129.90   1413.8
1108          8/30/2013   1396.43   1396.43
1108          8/31/2013   89.95     1735.65
1108          8/31/2013   495.95    1735.65
1108          8/31/2013   495.95    1735.65
1108          8/31/2013   633.85    1735.65
1108          8/31/2013   19.95     1735.65
1205          8/3/2013    2389.09   2389.09

并使用我从较早的问题[Here]中得到的答案,我想我并不完全理解 SQL....

所以 .....

我需要数据出来是这样的:

SalesPersonID   1       2       3       4       5     6     7     8     9      ….  29    30      31
1108            0.00    7713.80 3635.35 3151.68 0.00  0.00  0.00  0.00  1413.80    0.00  1396.43 1735.65
1205            0.00    0.00    2389.09 0.00    0.00  0.00  0.00  0.00  0.00       0.00  0.00    0.00

顶部的数字是所选月份的天数,我使用的是 8 月,如果选择 6 月,则只有 30 天。

我使用此代码来获取我的第一天和最后一天以及日期。

DECLARE @BeginDate AS VARCHAR(10), @EndDate AS VARCHAR(10), @SelectedMonthDays AS int
SET @BeginDate='08/15/13'

-- Last Day of Current Month
Set @SelectedMonthDays = DATEPART(day, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@BeginDate)+1,0)))

-- Last day Date of Current Month
SET @EndDate=cast(convert(date,DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@BeginDate)+1,0))) as varchar(10))

-- Convert input date to the first day Date of current month
Set @BeginDate = cast(convert(date,DATEADD(s,0,DATEADD(mm, DATEDIFF(m,0,@BeginDate),0))) as varchar(10))

要获取当前选定月份的天数,我有以下代码:

SELECT xhours = number FROM Master..spt_values WHERE type = N'P' and number between 1 and @SelectedMonthDays ORDER BY number

感谢您提供的任何帮助。

4

1 回答 1

3

这种类型的数据转换称为PIVOT

如果您提前知道所需的值,则可以对查询进行硬编码,基本语法为:

SELECT salespersonid, 
       COALESCE([1], 0.00)  AS [1], 
       COALESCE([2], 0.00)  AS [2], 
       COALESCE([3], 0.00)  AS [3], 
       COALESCE([4], 0.00)  AS [4]
FROM   
(
    SELECT salespersonid, 
        [order], 
        Datepart(day, transdate) day 
    FROM   yourtable 
    WHERE  transdate >= '2013-08-01' 
        AND transdate <= '2013-08-31'
) x 
PIVOT 
(
    Sum([order]) 
    FOR day IN ([1], [2], [3], [4]) 
) p 

但是,如果您想根据每个月的天数调整结果,您将需要考虑使用动态 SQL。您可以使用现有查询Master..spt_values来获取日期列表,您只需将该列表放在字符串中即可。动态 SQL 代码将类似于:

DECLARE @BeginDate AS VARCHAR(10), @EndDate AS VARCHAR(10), @SelectedMonthDays AS int
SET @BeginDate='08/15/13'

-- Last Day of Current Month
Set @SelectedMonthDays = DATEPART(day, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@BeginDate)+1,0)))

-- Last day Date of Current Month
SET @EndDate=cast(convert(date,DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@BeginDate)+1,0))) as varchar(10))

-- Convert input date to the first day Date of current month
Set @BeginDate = cast(convert(date,DATEADD(s,0,DATEADD(mm, DATEDIFF(m,0,@BeginDate),0))) as varchar(10))


DECLARE @cols AS NVARCHAR(MAX),
    @colsNull AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(number) 
                    from Master..spt_values 
                    WHERE type = N'P' 
                      and number between 1 and @SelectedMonthDays 
                    group by number
                    ORDER BY number
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @colsNull = STUFF((SELECT ', coalesce(' + QUOTENAME(number)+', 0.00) as '+QUOTENAME(number)
                    from Master..spt_values 
                    WHERE type = N'P' 
                      and number between 1 and @SelectedMonthDays 
                    group by number
                    ORDER BY number
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT SalesPersonID, ' + @colsNull + ' 
            from 
            (
                select SalesPersonID, [Order], 
                  datepart(day, TransDate) day
                from yourtable
                where TransDate>= '''+convert(varchar(10), @BeginDate, 120)+'''
                  and TransDate<= '''+convert(varchar(10), @EndDate, 120)+'''
            ) x
            pivot 
            (
                sum([Order])
                for day in (' + @cols + ')
            ) p '


execute sp_executesql @query;

请参阅SQL Fiddle with Demo。这给出了一个结果:

| SALESPERSONID | 1 |      2 |       3 |       4 | 5 | 6 | 7 | 8 |      9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |      30 |      31 |
|          1108 | 0 | 7713.8 | 3635.35 | 3151.68 | 0 | 0 | 0 | 0 | 1413.8 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 | 1396.43 | 1735.65 |
|          1205 | 0 |      0 | 2389.09 |       0 | 0 | 0 | 0 | 0 |      0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |       0 |       0 |
于 2013-09-05T19:33:01.093 回答