我来这里是为了根据类别获取记录。
我的表 foo 包含字段 [id,name,class] 。我的记录可以是:
1, ram, 10
2, hari, 9
3, sita, 10
4, gita, 9
5, rita, 5
6, tina, 7
8, nita, 8
9, bita, 5
10,seta, 7
......还有更多......
现在我想得到来自不同班级的每条记录的结果......即类似
1, ram, 10
2, hari, 9
5, rita, 5
6, tina, 7
8, nita, 8
,即根据班级 1 记录
答案 0 :(得分:6)
对于SQL Server 2005+和Oracle 9i +,请使用分析函数:
WITH summary AS (
SELECT f.id,
f.name,
f.class,
ROW_NUMBER() OVER (PARTITION BY f.class
ORDER BY f.name) AS rank
FROM FOO f)
SELECT s.id,
s.name,
s.class
FROM summary s
WHERE s.rank = 1
这也使用公用表表达式(CTE),在Oracle中称为子查询因子...
MySQL没有分析功能支持,所以你必须使用:
SELECT x.id,
x.name,
x.class
FROM (SELECT f.id,
f.name,
f.class,
CASE
WHEN @class = f.class THEN @rownum := @rownum + 1
ELSE @rownum := 1
END AS rank,
@class := f.class
FROM FOO f
JOIN (SELECT @rownum := 0, @class := '') r
ORDER BY f.class, f.name) x
WHERE x.rank = 1
答案 1 :(得分:4)
这应该是最简单的方法,不涉及任何特定于数据库的选项:
select *
from foo
where id in (select min(id)
from foo
group by class);
upd:是的,当然只有你每个班级只需要一条记录时这才有效。
upd2:只是为了好玩,想出一个查询,向您显示TOP N并且不涉及分析。看起来有点凌乱,但似乎工作:)
select newfoo.id, newfoo.name, newfoo.class
from (select class, max(r) top, min(r) bottom
from (select f.*, rownum r
from (select id, name, class from foo order by class, id asc) f)
group by class) minmax,
(select id, name, class, r
from (select f.*, rownum r
from (select id, name, class from foo order by class, id asc) f)) newfoo
where newfoo.class = minmax.class
and newfoo.r between minmax.bottom and
least(minmax.bottom + (TOP_N-1), minmax.top);
其中TOP_N
是您需要获取的记录数量。
答案 2 :(得分:3)
我在sql 2008中测试了这个并且对我有用,希望能以某种方式帮助你。
DECLARE @Class TABLE
(
id INT
,Name NVARCHAR(120)
,Class INT
PRIMARY KEY (id)
)
INSERT INTO @Class values (1, 'ram', 10)
INSERT INTO @Class values (2, 'hari', 9)
INSERT INTO @Class values (3, 'sita', 10)
INSERT INTO @Class values (4, 'gita', 9)
INSERT INTO @Class values (5, 'rita', 5)
INSERT INTO @Class values (6, 'tina', 7)
INSERT INTO @Class values (8, 'nita', 8)
INSERT INTO @Class values (9, 'bita', 5)
INSERT INTO @Class values (10, 'seta', 7)
SELECT A.id, A.Name, A.Class
FROM
(
SELECT ROW_NUMBER() OVER (PARTITION BY Class ORDER BY ID) as Num, ID, Name, Class
FROM @Class
) A
WHERE A.Num = 1
ORDER BY id
答案 3 :(得分:1)
使用SQL Server或Oracle(或实现该部分标准的任何其他引擎,包括免费的PostgreSQL),OVER
子句中的“窗口函数”(例如,参见here对于MS的文档,关于它们)让它变得简单;例如,在this SO question中,请参阅@Darrel的答案(他选择了每个类别的前10名,你只需要前1名,变化应该是显而易见的; - )。
在MySql或其他不遵守有关OVER
条款的标准的引擎中,您可以使用@Bill的答案(适用于MySql,不适用于其他人)或@Matt(可能需要稍微改编,因为他正在回答SQL Server等使用SELECT TOP 10 ...
- 在MySql中SELECT ... LIMIT 10
! - )。
答案 4 :(得分:0)
这是另一种方式
DECLARE @foo TABLE(ID INT,Name VARCHAR(20),Class INT)
INSERT INTO @foo
SELECT 1,'ram', 10 UNION ALL
SELECT 2, 'hari', 9 UNION ALL
SELECT 3, 'sita', 10 UNION ALL
SELECT 4, 'gita', 9 UNION ALL
SELECT 5, 'rita', 5 UNION ALL
SELECT 6, 'tina', 7 UNION ALL
SELECT 8, 'nita', 8 UNION ALL
SELECT 9, 'bita', 5 UNION ALL
SELECT 10,'seta', 7
SELECT DISTINCT X.*
FROM @foo f
CROSS APPLY(SELECT TOP 1 * FROM @foo WHERE Class = f.Class) AS X