【问题标题】:Get User Data in a Formatted Way With Sql Query使用 Sql Query 以格式化方式获取用户数据
【发布时间】:2018-12-21 19:15:10
【问题描述】:

我需要在报告中显示格式化数据。我正在使用三个表,其中一个添加新用户,第二个用于他们的付款,最后一个用于如果任何用户辞职。所以这里是示例表和默认数据:

CREATE TABLE [dbo].[Entry]
(
    [EmpId] [int] IDENTITY(1,1) NOT NULL,
    [EmpName] [nvarchar](40) NULL,
    [Address] [nvarchar](100) NULL,
    [Email] [nvarchar](20) NULL,
    [EntryDate] [datetime] NULL
)

INSERT [dbo].[Entry] ([EmpId], [EmpName], [Address], [Email], [EntryDate]) 
VALUES (1, N'John', N'On Earth', N'john@abc.com', CAST(0x0000A58000000000 AS DateTime)),
       (2, N'Jack', N'On Earth', N'jack@abc.com', CAST(0x0000A5A800000000 AS DateTime)),
       (3, N'Jessi', N'On Earth', N'jessi@abc.com', CAST(0x0000A5CF00000000 AS DateTime)),
       (4, N'Jackson', N'On Earth', N'jackson@abc.com', CAST(0x0000A5E400000000 AS DateTime))

CREATE TABLE [dbo].[Payment]
(
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [EmpId] [int] NULL,
    [Payment] [float] NULL,
    [PayDate] [datetime] NULL
)

INSERT [dbo].[Payment] ([Id], [EmpId], [Payment], [PayDate]) 
VALUES (1, 1, 2000, CAST(0x0000A61800000000 AS DateTime)), (2, 1, 2000, CAST(0x0000A63600000000 AS DateTime)),
       (3, 1, 2000, CAST(0x0000A65500000000 AS DateTime)), (4, 1, 2000, CAST(0x0000A67400000000 AS DateTime)),
       (5, 2, 4000, CAST(0x0000A5DB00000000 AS DateTime)), (6, 2, 4000, CAST(0x0000A5F900000000 AS DateTime)),
       (7, 2, 4000, CAST(0x0000A61800000000 AS DateTime)), (8, 2, 4000, CAST(0x0000A63600000000 AS DateTime)),
       (9, 2, 4000, CAST(0x0000A65500000000 AS DateTime)), (10, 2, 4000, CAST(0x0000A67400000000 AS DateTime)),
       (11, 2, 4000, CAST(0x0000A69200000000 AS DateTime)), (12, 3, 6000, CAST(0x0000A65500000000 AS DateTime)),
       (13, 3, 6000, CAST(0x0000A67400000000 AS DateTime)), (14, 4, 8000, CAST(0x0000A7FF00000000 AS DateTime)),
       (15, 4, 8000, CAST(0x0000A98B00000000 AS DateTime))

CREATE TABLE [dbo].[Resign]
(
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [EmpId] [int] NULL,
    [ResignDate] [datetime] NULL,
    [Reason] [nchar](10) NULL
)

INSERT [dbo].[Resign] ([Id], [EmpId], [ResignDate], [Reason]) 
VALUES (1, 1, CAST(0x0000A69B00000000 AS DateTime), N'Resigned  '),
       (2, 2, CAST(0x0000A6C400000000 AS DateTime), N'Resigned')

每年所需的输出如下:

Year 2015

Month - Jan - Feb - Mar - Apr - May - Jun - Jul - Aug - Sep - Oct - Nov - Dec
Opening - 10 - 10 - 10 - 12 - 12 - 12 - 12 - 12 - 12 - 12 - 8 - 8 //Total no. of employee
Add     -  0 -  0 -  2 -  0 -  0 -  0 -  0 -  0 -  0 -  0 - 0 - 0 //Newly added
Left    -  0 -  0 -  0 -  0 -  0 -  0 -  0 -  0 -  0 -  4 - 0 - 0 //Resigned
Closing - 10 - 10 - 12 - 12 - 12 - 12 - 12 - 12 - 12 -  8 - 8 - 8 //Closing Total

Year 2016

Month - Jan - Feb - Mar - Apr - May - Jun - Jul - Aug - Sep - Oct - Nov - Dec
Opening - 8 ----Goes on in the similar way
Add -----
Left ----
Closing ----

因此,报告中应如何显示数据就很清楚了。虽然我知道报告中按年分组,并尝试过类似的按月显示数据,如下所示:

SELECT 
    DATEPART(YYYY, Q.PayDate) [YEAR], 
    COUNT(m.EmpId) Total,
    SUM(CASE WHEN DATENAME(MONTH, m.EntryDate) = 'January' THEN 1 ELSE 0 END) [JAN],
    SUM(CASE WHEN DATENAME(MONTH, m.EntryDate) = 'February' THEN 1 ELSE 0 END) [FEB]  
FROM 
    Entry m 
INNER JOIN 
    Payment q ON Q.EmpId = M.EmpId 
LEFT JOIN
    Resign OUT ON OUT.EmpId = m.EmpId 
WHERE 
    m.EmpId NOT IN (SELECT DISTINCT p.EmpId FROM Resign p)
    AND m.EmpId IN (SELECT DISTINCT k.EmpId FROM Payment k)
GROUP BY 
    DATEPART(YYYY, Q.PayDate), DATEPART(MM, m.EntryDate);

上述查询返回如下内容:

YEAR  Total JAN FEB
--------------------
2016  2     0   0
2017  1     0   0
2018  1     0   0

但我不确定如何在与给出的示例相同的查询行中显示新添加的以及已辞职的用户?

注意:我愿意接受任何查询语言。所以期待您的想法以适当的方式实施。

【问题讨论】:

  • “但我不确定如何在与给出的示例相同的查询行中显示新添加的以及已辞职的用户?”我认为您需要一个动态枢轴 SQL 查询“生成器”stackoverflow.com/questions/10404348/…
  • 看起来你可以用一些分组和矩阵来安排这个。我会试着找点时间解释一下。
  • 实现*傻自动更正...
  • 开盘价如何计算?一旦我知道这一点,我应该能够相当容易地想出一个解决方案
  • 开孔以总数计算。每年在系统中添加的用户数量@Alan Schofield。所以你可以说完全不。系统中的用户打开。

标签: sql sql-server sql-server-2008 reporting-services


【解决方案1】:

Oracle 解决方案。在第二行放置报告年份。

  • mc 统计每月的新员工和离职人数
  • t 是分层子查询,统计每个月的 openingclosing 值。第一部分,锚点,计算表entryresign 中的条目,这是我们的起点。对于这个锚,我们逐月附加值,在mc 中搜索它们
  • 最后一步是pivot 和订购,此处添加只是为了按您的要求提供数据。

查询:

with 
  y as (select 2016 yr from dual),
  mc as (   
    select mm, sum(a) a, sum(c) c
      from ( select extract (month from entrydate) mm, 1 a, 0 c
               from entry, y where extract(year from entrydate) = yr
             union all
             select extract (month from resigndate) mm, 0 a, 1 c
               from resign, y where extract(year from resigndate) = yr) 
      group by mm ),
  t(mm, o, a, r, c) as (
    select 0, 0, 0, 0, 
           ( (select count(1) from entry where extract(year from entrydate) < yr)
           - (select count(1) from resign where extract(year from resigndate) < yr) ) 
      from y
    union all
    select t.mm + 1, t.c, mc.a, mc.c, t.c + nvl(mc.a, 0) - nvl(mc.c, 0)
      from t left join mc on mc.mm = t.mm + 1 
      where t.mm + 1 <= 12)
select * 
    from (
        select * from t
            unpivot (cnt for type in (o, a, r, c)))
    pivot (sum(cnt) for mm in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12))
    order by case type when 'O' then 1 when 'A' then 2 
                       when 'R' then 3 when 'C' then 4 
             end

提供的数据和 2016 年的结果:

TYPE      1      2      3      4      5      6      7      8      9     10     11     12
---- ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------
O         0      1      2      3      4      4      4      4      4      4      3      2
A         1      1      1      1                                         0      0 
R         0      0      0      0                                         1      1 
C         1      2      3      4      4      4      4      4      4      3      2      2

它主要是标准 SQL,您可能需要将 extract 之类的函数更改为它们的 SQLServer 等效函数。希望这会有所帮助。

【讨论】:

  • 我试过你的查询@Ponder Stibbons。不幸的是,在 WITH 语句的开头出现了编译错误。是否可以转换为视图或存储过程,以便更容易在报告中显示而不是使用Oracle 10g 的报告工具?
【解决方案2】:

如果您计划运行其中的许多报告工具,那么您绝对应该将精力转移到 SSRS 等报告工具上。它会多次简化事情。话虽如此,这是产生上述结果的一种方法。

DECLARE @Entry TABLE
(
    [EmpId] [int]  NOT NULL,
    [EmpName] [nvarchar](40) NULL,
    [Address] [nvarchar](100) NULL,
    [Email] [nvarchar](20) NULL,
    [EntryDate] [datetime] NULL
)

INSERT @Entry ([EmpId], [EmpName], [Address], [Email], [EntryDate]) 

VALUES
       (100, N'Early', N'On Earth', N'john@abc.com', '01/01/2015'),
       (1, N'John', N'On Earth', N'john@abc.com', CAST(0x0000A58000000000 AS DateTime)),
       (2, N'Jack', N'On Earth', N'jack@abc.com', CAST(0x0000A5A800000000 AS DateTime)),
       (3, N'Jessi', N'On Earth', N'jessi@abc.com', CAST(0x0000A5CF00000000 AS DateTime)),
       (4, N'Jackson', N'On Earth', N'jackson@abc.com', CAST(0x0000A5E400000000 AS DateTime))

DECLARE @Payment TABLE 
(
    [Id] [int]  NOT NULL,
    [EmpId] [int] NULL,
    [Payment] [float] NULL,
    [PayDate] [datetime] NULL
)

INSERT @Payment ([Id], [EmpId], [Payment], [PayDate]) 
VALUES (1, 1, 2000, CAST(0x0000A61800000000 AS DateTime)), (2, 1, 2000, CAST(0x0000A63600000000 AS DateTime)),
       (3, 1, 2000, CAST(0x0000A65500000000 AS DateTime)), (4, 1, 2000, CAST(0x0000A67400000000 AS DateTime)),
       (5, 2, 4000, CAST(0x0000A5DB00000000 AS DateTime)), (6, 2, 4000, CAST(0x0000A5F900000000 AS DateTime)),
       (7, 2, 4000, CAST(0x0000A61800000000 AS DateTime)), (8, 2, 4000, CAST(0x0000A63600000000 AS DateTime)),
       (9, 2, 4000, CAST(0x0000A65500000000 AS DateTime)), (10, 2, 4000, CAST(0x0000A67400000000 AS DateTime)),
       (11, 2, 4000, CAST(0x0000A69200000000 AS DateTime)), (12, 3, 6000, CAST(0x0000A65500000000 AS DateTime)),
       (13, 3, 6000, CAST(0x0000A67400000000 AS DateTime)), (14, 4, 8000, CAST(0x0000A7FF00000000 AS DateTime)),
       (15, 4, 8000, CAST(0x0000A98B00000000 AS DateTime))

DECLARE  @Resign TABLE
(
    [Id] [int]  NOT NULL,
    [EmpId] [int] NULL,
    [ResignDate] [datetime] NULL,
    [Reason] [nchar](10) NULL
)

INSERT @Resign ([Id], [EmpId], [ResignDate], [Reason]) 
VALUES (1, 1, CAST(0x0000A69B00000000 AS DateTime), N'Resigned  '),
       (2, 2, CAST(0x0000A6C400000000 AS DateTime), N'Resigned')

DECLARE @StartDate DATETIME = '01/01/2015'
DECLARE @EndDate DATETIME = '12/01/2016'

;WITH Calendar as
 (
    SELECT CalendarDate = @StartDate, CalendarYear = DATEPART(YEAR, @StartDate), CalendarMonth = DATEPART(MONTH, @StartDate)
    UNION ALL
    SELECT CalendarDate = DATEADD(MONTH, 1, CalendarDate),  CalendarYear = DATEPART(YEAR, CalendarDate), CalendarMonth = DATEPART(MONTH, CalendarDate)
    FROM Calendar
    WHERE DATEADD (MONTH, 1, CalendarDate) <= @EndDate
 )
 ,Employees AS
 (
     SELECT
        E.EmpID,
        StartDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, EntryDate), 0),
        EndDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, ResignDate), 0)
    FROM     
        @Entry E
        LEFT OUTER JOIN @Resign R ON R.EmpId = E.EmpId
)
,NormalizedAndUnpivoted AS
(
    SELECT
        *,
        CalendarMonth = DATEPART(MONTH,CalendarDate),
        CalendarYear = DATEPART(YEAR,CalendarDate),
        GroupField = CAST(DATEPART(MONTH,CalendarDate) AS NVARCHAR(50))+'_'+CAST(DATEPART(YEAR,CalendarDate) AS NVARCHAR(50)),
        SortOrder = CASE 
            WHEN Property='Opening' THEN 1
            WHEN Property='Addition'  THEN 2
            WHEN Property='Subtraction'  THEN 3
            WHEN Property='Total'  THEN 4
        END
    FROM
    (
        SELECT 
            C.CalendarDate,
            Opening =  COUNT(DISTINCT EmpExisting.EmpID) ,
            Addition = COUNT(DISTINCT EmpStarted.EmpID),
            Subtraction = COUNT(DISTINCT EmpEnd.EmpID),
            Total = COUNT(DISTINCT EmpExisting.EmpID) + COUNT(DISTINCT EmpStarted.EmpID) - COUNT(DISTINCT EmpEnd.EmpID)
        FROM 
            Calendar C
            LEFT OUTER JOIN Employees EmpExisting ON EmpExisting.StartDate < C.CalendarDate AND (EmpExisting.EndDate IS NULL OR EmpExisting.EndDate >=  C.CalendarDate)
            LEFT OUTER JOIN Employees EmpStarted ON EmpStarted.StartDate = C.CalendarDate
            LEFT OUTER JOIN Employees EmpEnd ON EmpEnd.EndDate = C.CalendarDate
        GROUP BY
            C.CalendarDate      
    )AS X
    UNPIVOT(
        PivotValue FOR Property IN (Opening, Addition, Subtraction, Total)
    ) AS U
)
,Pivoted AS
(
    SELECT
        CalendarYear,
        Property,
        SortOrder,
        Janurary=SUM(CASE WHEN CalendarMonth=1 THEN PivotValue ELSE NULL END),
        Feburary=SUM(CASE WHEN CalendarMonth=2 THEN PivotValue ELSE NULL END),
        March=SUM(CASE WHEN CalendarMonth=3 THEN PivotValue ELSE NULL END),
        April=SUM(CASE WHEN CalendarMonth=4 THEN PivotValue ELSE NULL END),
        May=SUM(CASE WHEN CalendarMonth=5 THEN PivotValue ELSE NULL END),
        June=SUM(CASE WHEN CalendarMonth=6 THEN PivotValue ELSE NULL END),
        July=SUM(CASE WHEN CalendarMonth=7 THEN PivotValue ELSE NULL END),
        August=SUM(CASE WHEN CalendarMonth=8 THEN PivotValue ELSE NULL END),
        September=SUM(CASE WHEN CalendarMonth=9 THEN PivotValue ELSE NULL END),
        October=SUM(CASE WHEN CalendarMonth=10 THEN PivotValue ELSE NULL END),
        November=SUM(CASE WHEN CalendarMonth=11 THEN PivotValue ELSE NULL END),
        December=SUM(CASE WHEN CalendarMonth=12 THEN PivotValue ELSE NULL END)
    FROM
        NormalizedAndUnpivoted
    GROUP BY
        CalendarYear,
        Property,
        SortOrder
)

SELECT * FROM Pivoted
ORDER BY
    CalendarYear,
    SortOrder
OPTION (MAXRECURSION 1000)

结果:

CalendarYear Property                       SortOrder   Janurary    Feburary    March       April       May         June        July        August      September   October     November    December
------------ ------------------------------ ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
2015         Opening                        1           0           1           1           1           1           1           1           1           1           1           1           1
2015         Addition                       2           1           0           0           0           0           0           0           0           0           0           0           0
2015         Subtraction                    3           0           0           0           0           0           0           0           0           0           0           0           0
2015         Total                          4           1           1           1           1           1           1           1           1           1           1           1           1
2016         Opening                        1           1           2           3           4           5           5           5           5           5           5           4           3
2016         Addition                       2           1           1           1           1           0           0           0           0           0           0           0           0
2016         Subtraction                    3           0           0           0           0           0           0           0           0           0           1           1           0
2016         Total                          4           2           3           4           5           5           5           5           5           5           4           3           3

【讨论】:

  • 这很好用@Ross Bush。正如您所写的即将转移报告工具,假设我将使用Crystal Report。那么如何或有可能让它更容易一些,比如创建一个视图并让它工作呢?
  • 很高兴您发现它很有用。 SQL 对于创建报告不是很有用。这就是为什么要超时创建报告工具集的原因。我通常会从返回所有需要的字段并加入此报告的三个表的存储过程中提取详细数据......让报告工具完成所有的展开、折叠、总计等。如果这满足您的问题,请标记为回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-04
  • 2014-06-10
  • 1970-01-01
  • 1970-01-01
  • 2021-05-16
  • 2015-12-18
相关资源
最近更新 更多