TSQL While Loop在一年中持续数月

时间:2014-08-19 21:43:05

标签: sql-server tsql

我有一个我需要实现的输出,我不太确定如何去做。

我首先需要在年中循环每个月并在select语句中使用该月来检查数据。

例如:

Select * from table where MONTH(A.[submissionDate]) = 1
Select * from table where MONTH(A.[submissionDate]) = 2
Select * from table where MONTH(A.[submissionDate]) = 3

我的最终结果是创建此XML输出以与图表插件一起使用。它需要包括几个月,即使没有数据,这就是为什么我想循环每个月来检查它。

    <root>
   <dataSet>
      <areaDesc>Area 1</areaDesc>
      <data>
         <month>January</month>
         <monthValue>1</monthValue>
         <submissions>0</submissions>
      </data>
      <data>
         <month>February</month>
         <monthValue>2</monthValue>
         <submissions>7</submissions>
      </data>
      <data>
         <month>March</month>
         <monthValue>3</monthValue>
         <submissions>5</submissions>
      </data>
   </dataSet>
   <dataSet>
      <areaDesc>Area 2</areaDesc>
      <data>
         <month>January</month>
         <monthValue>1</monthValue>
         <submissions>0</submissions>
      </data>
      <data>
         <month>February</month>
         <monthValue>2</monthValue>
         <submissions>7</submissions>
      </data>
      <data>
         <month>March</month>
         <monthValue>3</monthValue>
         <submissions>5</submissions>
      </data>
   </dataSet>
</root>

我可能会想到这一点,但我希望我说话可以帮助我一点点。

以下是我目前如何获得其他统计数据的建议:

--Temp table     
DECLARE @areas TABLE (
    area VARCHAR (100));
IF @dept = 'global'
   OR @dept = ''
    BEGIN
        INSERT INTO @areas (area)
        SELECT DISTINCT(AreaDesc)
        FROM dbo.EmpTable;
    END
ELSE
    BEGIN
        INSERT INTO @areas
        SELECT @dept;
    END

IF (@action = 'compare')
        BEGIN
            SELECT   DATENAME(month, A.[submissionDate]) AS [month],
                     MONTH(A.[submissionDate]) AS [monthValue],
                     count(A.[submissionID]) AS submissions,
                     B.[AreaDesc]
            FROM     empowermentSubmissions AS A
            INNER JOIN empTable AS B
            ON A.[nomineeQID] = B.[QID]
            WHERE    YEAR(A.[submissionDate]) = @year
                     AND A.[statusID] = 3
                     AND A.[locationID] IN (SELECT location
                                            FROM   @table)
            GROUP BY DATENAME(month, A.[submissionDate]), MONTH(A.[submissionDate]), B.[AreaDesc]
            ORDER BY [monthValue] ASC
            FOR      XML PATH ('dataSet'), TYPE, ELEMENTS, ROOT ('root');
        END
    ELSE

3 个答案:

答案 0 :(得分:2)

这是“日期”表或视图的绝佳应用程序。使用以下架构在数据库中创建新表:

CREATE TABLE dbo.Dates (
    Month INT,
    MonthName VARCHAR(20)
)

使用您可能希望聚合的年份和月份填充此表。然后,您可以进行如下查询:

SELECT 
    Area
    Dates.MonthName,
    COUNT(*) AS Count
FROM
    dbo.Dates
LEFT OUTER JOIN
    dbo.Submissions
        AND Dates.Month = MONTH(Submissions.SubmissionDate)
GROUP BY
    Dates.MonthName,
    Area

LEFT OUTER JOIN将为日期表中的每个年份和月份提供一行,以及该月份的任何提交的计数。你得到的结果如下:

Area    | MonthName | Count
Area 1  | Jan       | 0
Area 2  | Feb       | 2

&安培; C。

答案 1 :(得分:1)

您应该可以使用计数表来获得月份:

SELECT TOP 12 IDENTITY(INT,1,1) AS N
INTO #tally
FROM master.dbo.syscolumns sc1

SELECT DATENAME(MONTH,DATEADD(MONTH,t.N-1,'2014-01-01')) AS namemonth, t.N AS monthvalue, COUNT(tbl.submissionDate) AS submissions, tbl.Area
FROM #tally t
LEFT OUTER JOIN tbl ON MONTH(tbl.submissionDate) = t.N
GROUP BY t.n, tbl.Area

DROP TABLE #tally

答案 2 :(得分:1)

我想,你想要做一个FOR XML结构,以便一次性找到你想要的确切结果集。我把它与我可以收集的关于你的XML的内容放在一起。只需将表变量的名称更改为您的真实表名,这应该可以。

编辑:更改了查询以匹配发布查询中的定义。更新了data元素where子句,以便在一个月内找到零计数时维护月实例化。

编辑:已添加状态要求。

编辑:移动了持续月份输出的areaDesc标准。

declare @empowermentSubmissions table (submissionID int primary key identity(1,1), submissionDate datetime, nomineeQID INT, statusID INT)
declare @empTable table (QID int primary key identity(1,1), AreaDesc varchar(10))
declare @n int = 1

while @n < 50
begin
    insert into @empTable (AreaDesc) values ('Area ' + cast((@n % 2)+1 as varchar(1)))
    set @n = @n + 1
end
set @n = 1
while @n < 500
begin
    insert into @empowermentSubmissions (submissionDate, nomineeQID, StatusID) values (dateadd(dd,-(cast(rand()*600 as int)),getdate()), (select top 1 QID from @empTable order by newid()), 3 + (@n % 2) - (@n % 3) )
    set @n = @n + 1
end


declare @year int = 2014

select (
    select (
        select (
            select e1.areaDesc
            from @empTable e1
            where e1.areaDesc = e2.areaDesc
            group by e1.areaDesc
            for xml path(''),type
            )
            , (
                select [month], [monthValue], count(s1.submissionID) as submissions
                from (
                    select @year [Year]
                        , datename(month,dateadd(mm,RowID-1,@year-1900)) [Month]
                        , month(dateadd(mm,RowID-1,@year-1900)) [MonthValue]
                    from (
                        select *, row_number()over(order by name) as RowID
                        from master..spt_values
                        ) d
                    where d.RowID <= 12
                    ) t
                    left join (
                        select s3.submissionID, s3.submissionDate, e3.AreaDesc
                        from @empowermentSubmissions s3
                            inner join @empTable e3 on s3.nomineeQID = e3.QID
                        where s3.statusID = 3
                            and e3.areaDesc = e2.areaDesc
                        ) s1 on year(s1.submissionDate) = t.[Year]
                        and month(s1.submissionDate) = t.[MonthValue]
                group by [Month], [MonthValue]
                order by [MonthValue]
                for xml path('data'),type
            )
        for xml path(''),type
        ) dataset
    from @empowermentSubmissions s2
        inner join @empTable e2 on s2.nomineeQID = e2.QID
    group by e2.areaDesc
    for xml path(''), type
    ) root
for xml path (''), type