【问题标题】:SQL Server Detail Query with totals and grand totals带有总计和总计的 SQL Server 详细信息查询
【发布时间】:2015-02-22 20:54:51
【问题描述】:

我正在尝试生成单个 SQL 查询结果集,该结果集将允许我重现详细的计费报告,其中包含按位置的总计,以及最后所有位置的总计。 (我们从 Crystal Reports 移植)

不幸的是,详细信息在许多表中连接在一起,并没有我找到的示例那么简单。

这是我想要的数据输出:

ID  LastName  FirstName  Location  TestDateTime  ReaderLastName    ReaderFirstName   FeeCharged
1   Test      Mary       MyTown    12/01/2014    Smith             Tom              10
2   Test      John       MyTown    12/02/2014    Smith             Tom              10
                         MyTown                                                     20
3   Testing   Andy       YourTown  12/12/2014    Cabin             Fred             15
4   Jones     Lou        YourTown  12/13/2014    Cabin             Fred             15
5   Sun       Mike       YourTown  12/15/2014    Boat              Karen            15
                         YourTown                                                   45
                         All                                                        65

这是我到目前为止所做的,即获取我正在寻找的两个独立部分...首先是详细信息部分,按位置汇总:

SELECT
    tpd.ID, 
    tpd.LastName,
    tpd.FirstName,
    cl.Location, 
    ttd.TestDateTime, 
    ttd.ReaderLastName, 
    ttd.ReaderFirstName,
    cld.FeeCharged 
FROM   ((tstTestDemographics ttd 
INNER JOIN cfgLocationsDispatches cld 
ON ttd.Location=cld.LocationID) 
INNER JOIN tstPatientDemographics tpd 
ON ttd.TestID=tpd.TestID) 
INNER JOIN cfgLocations cl
ON cld.LocationID=cl.LocationID
WHERE  ttd.TestStatus=1 AND tpd.TestID>0 
AND cld.FeeCharged<>0 
AND (ttd.TestDateTime>={ts '2014-11-01 00:00:00'} 
AND ttd.TestDateTime<{ts '2014-12-01 00:00:00'})
ORDER BY cl.Location, ttd.TestDateTime
COMPUTE SUM(cld.FeeCharged)  BY cl.Location

然而,这会产生多个集合,我宁愿拥有一个大集合。

到目前为止,这是我对小计和总计的查询:

SELECT 
    CASE WHEN (Grouping(cl.Location) = 1) THEN 'Grand Total for Month'
    ELSE ISNULL(cl.Location, 'UNKNOWN')
    END as LocationName, 
    SUM(cld.FeeCharged) as 'FeeCharged Total'
FROM   ((tstTestDemographics ttd 
INNER JOIN cfgLocationsDispatches cld 
ON ttd.Location=cld.LocationID) 
INNER JOIN tstPatientDemographics tpd 
ON ttd.TestID=tpd.TestID) 
INNER JOIN cfgLocations cl
ON cld.LocationID=cl.LocationID
WHERE  ttd.TestStatus=1 AND tpd.TestID>0 
AND cld.FeeCharged<>0 
AND (ttd.TestDateTime>={ts '2014-11-01 00:00:00'} 
AND ttd.TestDateTime<{ts '2014-12-01 00:00:00'})
GROUP BY cl.Location WITH ROLLUP

有什么方法可以让我在一个大查询中获取详细列表以及小计和总计?

我对分组的尝试给了我很多我并不真正想要的重复值和空值。 我是汇总和分组功能的新手。我认为我的数据库是 SQL Server 2005,因为某些高级 2008 分组语法不起作用。

【问题讨论】:

    标签: sql sql-server-2005 group-by calculated-columns


    【解决方案1】:

    您希望将Fee Charged 相加。使用grouping sets,基本上第一次查询:

    SELECT tpd.ID, tpd.LastName, tpd.FirstName,
           (CASE WHEN (Grouping(cl.Location) = 1) THEN 'ALL' ELSE cl.Location END) as location,
           ttd.TestDateTime,
           ttd.ReaderLastName, ttd.ReaderFirstName,
           SUM(cld.FeeCharged) as FeeCharged
    FROM tstTestDemographics ttd INNER JOIN
         cfgLocationsDispatches cld 
         ON ttd.Location=cld.LocationID INNER JOIN
         tstPatientDemographics tpd ON
         ttd.TestID = tpd.TestID INNER JOIN
         cfgLocations cl
         ON cld.LocationID = cl.LocationID
    WHERE ttd.TestStatus = 1 AND tpd.TestID > 0 AND
          cld.FeeCharged <> 0 AND
          (ttd.TestDateTime>={ts '2014-11-01 00:00:00'} AND
           ttd.TestDateTime<{ts '2014-12-01 00:00:00'}) 
    GROUP BY GROUPING SETS((tpd.ID, tpd.LastName, tpd.FirstName, cl.Location, ttd.TestDateTime, ttd.ReaderLastName, ttd.ReaderFirstName),
                           (cl.location)
                          ) 
    ORDER BY cl.Location, ttd.TestDateTime
    

    编辑:

    在 SQL Server 2005 中,您可以使用联合来执行此操作。我会将大部分逻辑放在 CTE 中,所以重复它很容易。查询看起来像这样:

    WITH CTE as (
          SELECT tpd.ID, tpd.LastName, tpd.FirstName, cl.Location,
                 ttd.TestDateTime, ttd.ReaderLastName, ttd.ReaderFirstName, cld.FeeCharged
          FROM tstTestDemographics ttd INNER JOIN
               cfgLocationsDispatches cld 
               ON ttd.Location=cld.LocationID INNER JOIN
               tstPatientDemographics tpd ON
               ttd.TestID = tpd.TestID INNER JOIN
               cfgLocations cl
               ON cld.LocationID = cl.LocationID
          WHERE ttd.TestStatus = 1 AND tpd.TestID > 0 AND
                cld.FeeCharged <> 0 AND
                (ttd.TestDateTime>={ts '2014-11-01 00:00:00'} AND
                 ttd.TestDateTime<{ts '2014-12-01 00:00:00'}) 
         )
    SELECT t.*
    FROM ((select id, lastname, firtstname, location, testdatetime, readerlastname, readerfirstname,
                  sum(feecharged) as feecharged
           from cte
           group by id, lastname, firtstname, location, testdatetime, readerlastname, readerfirstname
          ) union all
          (select NULL, NULL, NULL, location, NULL, NULL, NULL,
                  sum(feecharged) as feecharged
           from cte
           group by location
          )
         ) t
    ORDER BY location, (case when id is null then 2 else 1 end);
    

    【讨论】:

    • 谢谢,戈登。我的数据库返回“'SETS' 附近的语法不正确”。我想知道我的数据库是否不支持分组集。
    • 我已经验证我的数据库是 SQL Server 2005,所以我不能做分组集,所以这不起作用,虽然它比我得到的更多。
    • 这很棒。谢谢,戈登。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-10
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多