这是挑战你的SQL拼图:
编写一个查询,选择三个不同类别中的前5个记录。
这样的事情:
select top 5 name, age from table1 where category = 22 order by age desc
union all
select top 5 name, age from table1 where category = 27 order by age desc
union all
select top 5 name, age from table1 where category = 53 order by age desc
但是没有使用UNION或UNION ALL
如果您使用某些特定于供应商的SQL扩展,请指定您正在使用的数据库。
答案 0 :(得分:3)
经典top-n-per-group
,不是吗?
使用SQL Server语法。 ROW_NUMBER()
应该在2015年的所有体面的数据库中。
WITH
CTE
AS
(
select
name
,age
,ROW_NUMBER() OVER (PARTITION BY category ORDER BY age desc) AS rn
from table1
where category IN (22, 27, 53)
)
SELECT
name
,age
FROM CTE
WHERE rn <= 5
;
UNION
在某种意义上与OR
相同。
如果您的表有主键ID
,您可以像这样重写查询:
SELECT name, age
FROM table1
WHERE
ID IN (select top 5 ID from table1 where category = 22 order by age desc)
OR
ID IN (select top 5 ID from table1 where category = 27 order by age desc)
OR
ID IN (select top 5 ID from table1 where category = 53 order by age desc)
通常情况下,UNION ALL
会比这更有效率。
答案 1 :(得分:3)
如果你真的想要前5名,那么你可能需要打破平局。每name
个age
是唯一的吗?
select t.name, t.age from T t
where t.category in (22, 27, 53) and 5 >= (
select count(*) from T t2
where t2.category = t.category
and (t2.age >= t.age or t2.age = t.age and t2.name >= t.name)
)
答案 2 :(得分:2)
如果您使用某些特定于供应商的SQL扩展,请指定 你正在使用的数据库。
在 SQL Server 中,您可以使用排名功能ROW_NUMBER()
和PARTITION BY category
来为每个类别组生成排名,并且过滤您正在寻找的三个类别。然后,您可以过滤以仅获得排名数小于5的行,这将为您获得每个类别的最早的5个名称:
SELECT name, age
FROM
(
SELECT
name, age,
ROW_NUMBER() OVER(PARTITION BY category ORDER BY age DESC)AS RN
FRO< table1
WHERE category IN(22,27, 53)
) AS t
WHERE RN <= 5;
答案 3 :(得分:1)
使用自联接可以昂贵地模拟排名。对于具有执行自连接的子选择的解决方案,这是伪SQL(即,可能需要一些语法调整)。这是你的意思吗?
select name, age from (
select a.name,a.age, count(*) as rank from
table1 a join table1 b on a.category=b.category
where a.category in (22,27,53) and
((b.age+hash(b.name,b.age) >=a.age+hash(a.name,a.age))
) c
group by c.name, c.age
where rank <= 5