【问题标题】:Issue regarding showing pivot data in sql server关于在 sql server 中显示数据透视数据的问题
【发布时间】:2015-09-01 14:38:01
【问题描述】:

我处于需要形成一个复杂的 sql 以显示与 datagridview in winform apps 类似的界面的情况。我已经完成了以表格形式编写代码的工作。现在我想用 sql 在数据库级别形成日历。这是我的用户界面的样子

现在我必须使用 sql 在数据库级别生成上述输出。在这里,我给出了下面的 sql,它几乎给出了正确的数据,但仍然存在一个小问题。先看sql

DECLARE @MonthNo INT
DECLARE @Year INT

SET @MonthNo = 1
SET @Year = 2011

;WITH DataToPivot AS
(   SELECT  s.SpecialistID,
            s.Name, 
            DayNumber = DATEPART(DAY, h.EntryDate),
            HoursData = CASE WHEN DATEPART(WEEKDAY, h.EntryDate) IN (6, 7) THEN CONVERT(VARCHAR(10), 'S')
                            WHEN h.HoursData IS NULL THEN '8.00'
                            ELSE h.HoursData
                        END
    FROM    Specialists AS s
            LEFT JOIN HourSheet AS h
                ON h.SpecialistID = s.SpecialistID
                AND Month(h.EntryDate)= @MonthNo
                AND Year(h.EntryDate) = @Year
    WHERE   s.IsActive = 1 
    AND     s.IsSpecialist = 1 
    AND     s.IsExcluded = 0
)

select * from DataToPivot

SELECT  pvt.SpecialistID,
        pvt.Name,
        [1] = ISNULL(pvt.[1], '8.00'),
        [2] = ISNULL(pvt.[2], '8.00'),
        [3] = ISNULL(pvt.[3], '8.00'),
        [4] = ISNULL(pvt.[4], '8.00'),
        [5] = ISNULL(pvt.[5], '8.00'),
        [6] = ISNULL(pvt.[6], '8.00'),
        [7] = ISNULL(pvt.[7], '8.00'),
        [8] = ISNULL(pvt.[8], '8.00'),
        [9] = ISNULL(pvt.[9], '8.00'),
        [10] = ISNULL(pvt.[10], '8.00'),
        [11] = ISNULL(pvt.[11], '8.00'),
        [12] = ISNULL(pvt.[12], '8.00'),
        [13] = ISNULL(pvt.[13], '8.00'),
        [14] = ISNULL(pvt.[14], '8.00'),
        [15] = ISNULL(pvt.[15], '8.00'),
        [16] = ISNULL(pvt.[16], '8.00'),
        [17] = ISNULL(pvt.[17], '8.00'),
        [18] = ISNULL(pvt.[18], '8.00'),
        [19] = ISNULL(pvt.[19], '8.00'),
        [20] = ISNULL(pvt.[20], '8.00'),
        [21] = ISNULL(pvt.[21], '8.00'),
        [22] = ISNULL(pvt.[22], '8.00'),
        [23] = ISNULL(pvt.[23], '8.00'),
        [24] = ISNULL(pvt.[24], '8.00'),
        [25] = ISNULL(pvt.[25], '8.00'),
        [26] = ISNULL(pvt.[26], '8.00'),
        [27] = ISNULL(pvt.[27], '8.00'),
        [28] = ISNULL(pvt.[28], '8.00'),
        [29] = ISNULL(pvt.[29], '8.00'),
        [30] = ISNULL(pvt.[30], '8.00'),
        [31] = ISNULL(pvt.[31], '8.00')
FROM    DataToPivot AS d
        PIVOT
        (   SUM(HoursData)
            FOR DayNumber IN 
            (   [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]
            ) 
        ) AS pvt
ORDER BY pvt.SpecialistID;

如果HoursData day 为空,如果日期为sunday or saturday,那么我需要显示S,如果日期不是sunday or saturday 但 HoursData 为空,那么我必须显示8:00 否则我需要显示值存储在HoursData

如何使用pivot sql 实现它。任何人都可以提供帮助或提出任何建议。

是否有可能第二个透视查询可以更短?

谢谢

编辑

表结构如下

工时表

SpecialistID INT
EntryDate    DATETIME
HoursData    decimal

专家

SpecialistID    INT
Name            varchar(50)

编辑 1

首先查看我的 sql,它与我想要的很接近,但仍需要一些更改

DECLARE @MonthNo INT
DECLARE @Year INT

SET @MonthNo = 1
SET @Year = 2011

;WITH DataToPivot AS
(   SELECT  s.SpecialistID,
            s.Name, 
            DayNumber = DATEPART(DAY, h.EntryDate),
            HoursData = CASE WHEN DATEPART(WEEKDAY, h.EntryDate) IN (6, 7) THEN CONVERT(VARCHAR(10), 'S')
                            WHEN h.HoursData IS NULL THEN '8.00'
                            ELSE h.HoursData
                        END
    FROM    Specialists AS s
            LEFT JOIN HourSheet AS h
                ON h.SpecialistID = s.SpecialistID
                AND Month(h.EntryDate)= @MonthNo
                AND Year(h.EntryDate) = @Year
    WHERE   s.IsActive = 1 
    AND     s.IsSpecialist = 1 
    AND     s.IsExcluded = 0
)

SELECT  pvt.SpecialistID,
        pvt.Name,
        [1] = ISNULL(pvt.[1], '8.00'),
        [2] = ISNULL(pvt.[2], '8.00'),
        [3] = ISNULL(pvt.[3], '8.00'),
        [4] = ISNULL(pvt.[4], '8.00'),
        [5] = ISNULL(pvt.[5], '8.00'),
        [6] = ISNULL(pvt.[6], '8.00'),
        [7] = ISNULL(pvt.[7], '8.00'),
        [8] = ISNULL(pvt.[8], '8.00'),
        [9] = ISNULL(pvt.[9], '8.00'),
        [10] = ISNULL(pvt.[10], '8.00'),
        [11] = ISNULL(pvt.[11], '8.00'),
        [12] = ISNULL(pvt.[12], '8.00'),
        [13] = ISNULL(pvt.[13], '8.00'),
        [14] = ISNULL(pvt.[14], '8.00'),
        [15] = ISNULL(pvt.[15], '8.00'),
        [16] = ISNULL(pvt.[16], '8.00'),
        [17] = ISNULL(pvt.[17], '8.00'),
        [18] = ISNULL(pvt.[18], '8.00'),
        [19] = ISNULL(pvt.[19], '8.00'),
        [20] = ISNULL(pvt.[20], '8.00'),
        [21] = ISNULL(pvt.[21], '8.00'),
        [22] = ISNULL(pvt.[22], '8.00'),
        [23] = ISNULL(pvt.[23], '8.00'),
        [24] = ISNULL(pvt.[24], '8.00'),
        [25] = ISNULL(pvt.[25], '8.00'),
        [26] = ISNULL(pvt.[26], '8.00'),
        [27] = ISNULL(pvt.[27], '8.00'),
        [28] = ISNULL(pvt.[28], '8.00'),
        [29] = ISNULL(pvt.[29], '8.00'),
        [30] = ISNULL(pvt.[30], '8.00'),
        [31] = ISNULL(pvt.[31], '8.00')
FROM    DataToPivot AS d
        PIVOT
        (   SUM(HoursData)
            FOR DayNumber IN 
            (   [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]
            ) 
        ) AS pvt
ORDER BY pvt.SpecialistID;

当我执行上面的 sql 然后输出就像

现在的问题是看到 Sarah Rodham 第一列,第二列显示 8.00,即星期日或星期六。所以首先我需要检查小时表中是否存在日期 1/JAN/2011 的数据,然后我将显示如果没有找到数据,那么我将检查日期是否与太阳或星期六有关.....如果是然后如果日期不是太阳或星期六,我将显示“S”,然后我将显示 8.00,这是我无法通过上述 sql 实现的。

现在告诉我你能如何帮助我。我还需要在这里发布什么信息。谢谢

编辑 2

DECLARE @Days AS INT
DECLARE @DateInput AS VARCHAR(10)
SET @DateInput = '01/01/2011'

SELECT @Days = DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,@DateInput),0)))
PRINT @Days

;WITH TotalDaysInMoth(MonthNumber) AS
(
    SELECT 1
    UNION ALL
    SELECT MonthNumber+1 
    FROM TotalDaysInMoth
    WHERE MonthNumber < @Days
)

select * from TotalDaysInMoth;

【问题讨论】:

  • 请提供专家和小时表的结构以及一些测试数据行...
  • 我用您要求的表格结构更新了我的帖子。如果可能,请查看并回答。
  • 请添加一些示例数据和预期输出。几行就足够了...
  • 还有一点:SQL Server 的哪个版本?

标签: c# sql-server winforms datagridview


【解决方案1】:

试试这个方法:

DECLARE @FirstOfMonth DATE={ts'2011-02-01 00:00:00'};

WITH DateBorders AS
(
    SELECT @FirstOfMonth AS FirstOfMonth
          ,DATEADD(DAY,-1,DATEADD(MONTH,1,@FirstOfMonth)) AS LastOfMonth 
)
,ThirtyOneNumbers(N) AS
(
        SELECT N FROM(VALUES (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))t(N)
)
,RunningDates AS
(
    SELECT N AS DayNumber
          ,DATEADD(DAY,N-1,DateBorders.FirstOfMonth) DayDate
    FROM ThirtyOneNumbers,DateBorders
    WHERE ThirtyOneNumbers.N<=DATEDIFF(DAY,DateBorders.FirstOfMonth,DateBorders.LastOfMonth) + 1
)
,RunningDatesExt AS
(
    SELECT RunningDates.*
          ,wd.WeekDayInx
    FROM RunningDates
    CROSS APPLY(SELECT DATEPART(WEEKDAY,DayDate)) AS wd(WeekDayInx)
)
,HourSheetSum AS
(
    SELECT hs.SpecialistID
          ,hs.EntryDate
          ,SUM(hs.HoursData) AS SumHoursData
    FROM HourSheet AS hs
    GROUP BY hs.SpecialistID,hs.EntryDate
)
,DataToPivot AS
(
    SELECT s.SpecialistID,
           s.Name, 
           rde.DayNumber,

           CASE WHEN h.SumHoursData IS NULL THEN CASE WHEN rde.WeekDayInx IN(6,7) THEN 'S'
                                                  ELSE '8.00'  
                                             END
                ELSE CAST(h.SumHoursData AS VARCHAR(100)) END AS HoursData

    FROM RunningDatesExt AS rde
         CROSS JOIN Specialists AS s
         LEFT JOIN HourSheetSum AS h ON h.SpecialistID=s.SpecialistID AND rde.DayDate=h.EntryDate
)
SELECT  pvt.*
FROM    DataToPivot AS d
        PIVOT
        (   MIN(HoursData)
            FOR DayNumber IN 
            (   [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]
            ) 
        ) AS pvt
ORDER BY pvt.SpecialistID;

【讨论】:

  • 我更新我的帖子,比如我正在寻找什么样的输出。如果可能,请查看我的编辑和答案。感谢您的宝贵时间。
  • @Thomas,找到一种新方法...您必须将 WHERE 放回查询...如果有帮助,请投票和/或标记为已接受,谢谢
  • 如果你了解我需要什么样的输出,你能提供新的 sql 查询吗?
  • @Thomas,看看我的回答。在那里你会发现新方法:-)
  • @Thomas,你搞错了……不需要你的“TotalDaysInMonth”,看看我的 CTE“DateBorders”。这已经在那里完成了。看看我的 CTE“RunningNumbers”。它将在一个月的最后一天停止。查看“短”月的输出。最后一列是 NULL...无论如何,您的想法是错误的...不要对动态 SQL 做任何丑陋的把戏。只需使用 C# 代码逻辑,根据月份的天数设置最后四列的可见性。请投票,那里有很多时间...... :-)
猜你喜欢
  • 2011-10-16
  • 2010-11-27
  • 2015-06-08
  • 2013-05-29
  • 1970-01-01
  • 2017-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多