[英]SQL Server - Only get a single row for each distinct value of a field
我剛從面試中回家,他們讓我參加編程測試。 真正難倒我的問題之一如下:
你是一所高中的老師,負責為即將到來的全國辯論錦標賽挑選最好的辯論隊。 給定以下表結構:
CREATE TABLE CompetitionResults ( StudentName NVARCHAR(255) NOT NULL, -- The student's name SchoolYear INT NOT NULL, -- The school year of the student at the time they entered the competition CompetitionDate DATE NOT NULL, -- The date of the competition CompetitionResult INT NOT NULL -- The student's final score in the competition (0 - 100) )
編寫一個查詢,根據他們之前的比賽結果返回即將舉行的比賽的最佳候選人的姓名。
約束:
- 返回單列
StudentName
。- 每個學年 (7 - 12) 只應挑選一名學生。
- 每個返校學生今年必須參加 3 場其他比賽。
特別是最后一個限制,我遇到了最大的麻煩。 這是我在時間用完后最終提交的內容:
SELECT
StudentName AS sn,
(SELECT COUNT(*) AS NumComps, CompetitionDate FROM CompetitionResults
WHERE YEAR(CompetitionDate) = 2020 AND NumComps = 3),
SchoolYear,
CompetitionDate,
CompetitionResult
FROM CompetitionResults
WHERE CompetitionDate IN (SELECT MIN(CompetitionDate)
FROM CompetitionResults GROUP BY CompetitionDate) AND
CompetitionResult IN (SELECT MAX(CompetitionResult) FROM
CompetitionResults WHERE StudentName = sn);
為了職業發展,我希望能夠在盡可能少的幫助下解決這個問題,但正如你可能會說的,我在這里真的很掙扎。 這段代碼甚至無法編譯,更不用說所有子查詢的性能影響了! 然而,我發現它們比連接更容易編碼,因此我在這里使用它們。
任何指導/提示將不勝感激。 MTIA :-)
對我來說,這基本上是聚合。 . . 有一點窗口函數:
select studentname, SchoolYear, avg_competitionscore
from (select studentname, SchoolYear, avg(competitionscore) as avg_competitionscore,
row_number() over (partition by SchoolYear order by avg(competitionscore) desc) as seqnum
from CompetitionResults cr
where year(CompetitionDate) = year(getdate())
group by studentname
having count(*) = 3
) s
where seqnum = 1;
子查詢匯總每個學生的比賽,應用適當的過濾條件——針對個人比賽和總人數。 外部查詢每年選擇一個。
我看不出三場比賽與最好的比賽有什么關系。 我懷疑根據分數選擇最好的學生的部分是一個“隱藏的要求”,用於區分僅可接受的解決方案和最佳解決方案。
我想可能有額外的邏輯來檢查每年是否至少有一名候選人,但問題表明至少有一名這樣的學生。
我想這可以用窗口函數來解決。 遵循一個例子 - 畢竟可能需要一些調整,但你應該明白:
DECLARE @t TABLE(
StudentName NVARCHAR(255)
,SchoolYear INT
,CompetitionDate DATE
,CompetitionResult INT
)
INSERT INTO @t VALUES
('Peter', 7, '2019-01-01', 100)
,('Peter', 8, '2020-01-01', 100)
,('Peter', 8, '2020-03-01', 100)
,('Paul', 10, '2020-01-01', 100)
,('Paul', 10, '2020-03-01', 100)
,('Paul', 10, '2020-04-01', 100)
,('Mary', 11, '2019-01-01', 100)
,('Mary', 11, '2019-02-01', 100)
,('Mary', 11, '2019-03-01', 100)
,('Jacob', 12, '2020-01-01', 100)
,('Jacob', 12, '2020-02-01', 100)
,('Jacob', 12, '2020-03-01', 100)
,('Jacob', 12, '2020-04-01', 90)
,('Jennifer', 9, '2020-03-01', 100)
,('Jennifer', 9, '2020-04-01', 100)
,('Jennifer', 9, '2020-05-01', 100)
,('Lucas', 12, '2020-03-01', 100)
,('Lucas', 12, '2020-04-01', 100)
,('Lucas', 12, '2020-05-01', 100)
;WITH cte AS(
SELECT *
,COUNT(CASE WHEN YEAR(CompetitionDate) = YEAR(GETDATE()) THEN 1 ELSE NULL END) OVER (PARTITION BY StudentName, YEAR(CompetitionDate)) AS CountCompYear
,ROW_NUMBER() OVER (PARTITION BY StudentName ORDER BY CompetitionDate DESC) AS LastCompetition
FROM @t
),
cteFilter AS(
SELECT *, ROW_NUMBER() OVER (PARTITION BY SchoolYear ORDER BY CompetitionResult DESC, StudentName ASC) AS DistStudent
FROM cte
WHERE CountCompYear = 3
AND LastCompetition = 1
)
SELECT *
FROM cteFilter
WHERE DistStudent = 1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.