SQL Server详细信息查询,包含总计和总计

时间:2014-12-24 20:40:19

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

我正在尝试生成单个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

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

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

1 个答案:

答案 0 :(得分:2)

您希望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中,您可以使用union来执行此操作。我将大部分逻辑放在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);