我正在尝试生成单个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分组语法不起作用。
答案 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);