[英]SQL Server : force results for all distinct values in aggregate
我試圖強制結果出現在我的結果集中一列的不同值。 換句話說,我希望任何不同的值都顯示為零,而不是在給定的組中沒有值的情況下掉落。
例如,我的數據大致如下:
ID |Quality | Date | Dollars
-------------------------------------
1 |Good | 02/28/15 | 1
2 |Better | 02/28/15 | 2
3 |Best | 02/28/15 | 3
4 |*Fair* | 02/28/15 | 1
1 |Good | 01/31/15 | 1
2 |Better | 01/31/15 | 2
3 |Best | 01/31/15 | 3
1 |Good | 12/31/15 | 1
3 |Best | 12/31/15 | 3
我給“ Fair”加注星標以引起注意,因為它會在結果集中引起明顯的“ fair”值。 但是,如果按“日期”分組,“公平”將不會再顯示任何其他月份。
我為解決該問題所做的努力似乎比必要的困難,但是我在弄清楚什么會更簡單時遇到了麻煩。 我想返回該表中最近兩個“日期”的所有不同“質量”結果的總和“美元”。
我已經完成以下工作:
declare @currdt date = '02/28/2015'
declare @prevdt date = DATEADD(d,-1,DATEADD(mm, DATEDIFF(m,0,@currdt),0)) --last day of month prior
declare @dates table (date1 date);
insert into @dates (date1) values (@currdt), (@prevdt);
with qualities (quality, date) as
(
select distinct quality, date1
from mytableA
join (select * from @dates) a on 1=1
),
history (ID, Quality, Add_Date, Dollars)
(
select ID, Quality, Add_Date, Dollars
from mytableA
where Add_Date <= @currdt
and Add_Date >= @prevdt
)
select
q.quality, q.date, sum(h.Dollars)
from
qualities q
left join
history h on h.quality = q.quality and h.date = q.date
group by
q.quality, q.date
根據上表所示的預期結果應如下:
Quality | Date | Dollars
------------------------------
Fair | 02/28/15 | 1
Good | 02/28/15 | 1
Better | 02/28/15 | 2
Best | 02/28/15 | 3
Fair | 01/31/15 | 0
Good | 01/31/15 | 1
Better | 01/31/15 | 2
Best | 01/31/15 | 3
我應該在給定的月份中列出一些重復的特質,以使總和更加有趣,但是希望這很清楚。
如果您的目標只是減少查詢長度,那么這應該與您現在所擁有的相同(並且它將輸出兩個日期的所有質量):
declare @currdt date = '02/28/2015'
declare @prevdt date = DATEADD(d,-1,DATEADD(mm, DATEDIFF(m,0,@currdt),0)) --last day of month prior
select a.quality, a.date, sum(isnull(b.Dollars,0)) as dollars
from (select quality, d.date from mytableA, (VALUES (@currdt), (@prevdt)) AS d(date) group by Quality, d.date) a
left join mytableA b on a.Date = b.date and a.Quality = b.Quality
group by a.quality, a.date
order by 2 desc, 3 asc
使用您的樣本數據,將輸出:
quality date dollars
Fair 2015-02-28 1
Good 2015-02-28 1
Better 2015-02-28 2
Best 2015-02-28 3
Fair 2015-01-31 0
Good 2015-01-31 1
Better 2015-01-31 2
Best 2015-01-31 3
如果您要保持質量的順序( fair -> good -> better -> best
),可以這樣做:
select a.quality, a.date, sum(isnull(b.Dollars,0)) as sum
from (select quality, sort, date from
(values (1, 'Fair'), (2, 'Good'), (3, 'Better'), (4, 'Best')) as q(sort, quality),
(values (@currdt), (@prevdt)) as d(date) group by q.quality, d.date, sort) a
left join mytableA b on a.Date = b.date and a.Quality = b.Quality
group by a.quality, a.date, sort
order by date desc, sort
如果我沒有列出質量的另一個表,這就是我會做的方法:
DECLARE @Table TABLE
(
ID INT IDENTITY
,RateableItemID INT
,Quality VARCHAR(15)
,Date DATE
,Dollars MONEY
)
INSERT INTO @Table
(
RateableItemID
,Quality
,Date
,Dollars
)
VALUES
(1 ,'Good' , '02/28/15' , 1 )
,(2 ,'Better' , '02/28/15' , 2 )
,(3 ,'Best' , '02/28/15' , 3 )
,(4 ,'Fair' , '02/28/15' , 1 )
,(1 ,'Good' , '01/31/15' , 1 )
,(2 ,'Better' , '01/31/15' , 2 )
,(3 ,'Best' , '01/31/15' , 3 )
,(1 ,'Good' , '12/31/15' , 1 )
,(3 ,'Best' , '12/31/15' , 3 )
SELECT
TwoMostRecentDates.Date
,Qualities.Quality
,ISNULL(SUM(Details.Dollars),0) AS DollarsForThisDateAndQuality
FROM
(
SELECT DISTINCT TOP 2
Date
FROM
@Table
ORDER BY Date DESC
) TwoMostRecentDates
CROSS JOIN
(
SELECT DISTINCT
Quality
FROM @Table
) Qualities
LEFT JOIN
@Table Details
ON TwoMostRecentDates.Date = Details.Date
AND Qualities.Quality = Details.Quality
GROUP BY
TwoMostRecentDates.Date
,Qualities.Quality
ORDER BY
TwoMostRecentDates.Date
,CASE
Qualities.Quality
WHEN 'Best' THEN 1
WHEN 'Better' THEN 2
WHEN 'Good' THEN 3
WHEN 'Fair' THEN 4
END
我認為對於所有代碼,可讀性都勝過字符數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.