在项目中选择数据时出现性能问题。
有一个包含3列的表:“id”,“time”和“group”
因此表数据可能如下所示:
ID | TIME | GROUP
------------------------
1 | 20090805 | A
2 | 20090804 | A
3 | 20090804 | B
4 | 20090805 | B
5 | 20090803 | A
6 | 20090802 | B
......等等。
现在的任务是在给定日期的每个组中选择“当前”条目(它们的ID)。也就是说,对于每个组,找到给定日期的最新条目。
遵循先决条件:
我目前所做的是一个多步骤过程,我想将其转换为单个SELECT语句:
SELECT DISTINCT group FROM table
查找可用的组SELECT * FROM table WHERE time<selectionDate AND group=loop ORDER BY time DESC
显然这不是最佳的。
如果一位经验丰富的SQL专家可以帮助我找到将这些步骤放在一个语句中的解决方案,我将非常高兴。
谢谢!
答案 0 :(得分:10)
以下内容适用于SQL Server 2005+和Oracle 9i +:
WITH groups AS (
SELECT t.group,
MAX(t.time) 'maxtime'
FROM TABLE t
GROUP BY t.group)
SELECT t.id,
t.time,
t.group
FROM TABLE t
JOIN groups g ON g.group = t.group AND g.maxtime = t.time
任何数据库都应该支持:
SELECT t.id,
t.time,
t.group
FROM TABLE t
JOIN (SELECT t.group,
MAX(t.time) 'maxtime'
FROM TABLE t
GROUP BY t.group) g ON g.group = t.group AND g.maxtime = t.time
答案 1 :(得分:5)
以下是我将如何在SQL Server中执行此操作:
SELECT * FROM table WHERE id in
(SELECT top 1 id FROM table WHERE time<selectionDate GROUP BY [group] ORDER BY [time])
答案 2 :(得分:1)
解决方案因数据库服务器而异,因为TOP查询的语法各不相同。基本上您正在寻找一个“每个组的前n个”查询,因此如果您愿意,可以使用Google。
这是SQL Server中的解决方案。以下将回归自1990年以来每年全垒打最多的前10名球员。关键是计算每个球员每年的“本垒打等级”。
select
HRRanks.*
from
(
Select
b.yearID, b.PlayerID, sum(b.Hr) as TotalHR,
rank() over (partition by b.yearID order by sum(b.hr) desc) as HR_Rank
from
Batting b
where
b.yearID > 1990
group by
b.yearID, b.playerID
)
HRRanks
where
HRRanks.HR_Rank <= 10
以下是Oracle(每个部门的销售人员)
的解决方案SELECT deptno, avg_sal
FROM(
SELECT deptno, AVG(sal) avg_sal
GROUP BY deptno
ORDER BY AVG(sal) DESC
)
WHERE ROWNUM <= 10;
或使用分析函数:
SELECT deptno, avg_sal
FROM (
SELECT deptno, avg_sal, RANK() OVER (ORDER BY sal DESC) rank
FROM
(
SELECT deptno, AVG(sal) avg_sal
FROM emp
GROUP BY deptno
)
)
WHERE rank <= 10;
或者同样,但使用DENSE_RANK()而不是RANK()
答案 3 :(得分:0)
select * from TABLE where (GROUP, TIME) in (
select GROUP, max(TIME) from things
where TIME >= 20090804
group by GROUP
)
使用MySQL测试(但我必须更改表名和列名,因为它们是关键字)。
答案 4 :(得分:0)
SELECT * 来自TABB T1
QUALIFY ROW_NUMBER()OVER(按GROUPP划分,TIMEE按ID desc排序)= 1