取每个分类N条数据 sql




写法一
SELECT *,
(SELECT COUNT(1) FROM T_Pray subTab WHERE T_Pray .UserId=subTab.UserId AND T_Pray .Id< subTab.Id)
< 2
FROM T_Pray
ORDER BY UserId,Id
上例取的是每个userid分类下两条数据(貌似在sql server 2014上不行,语句有问题)改成如下的写法,则都可以
SELECT * FROM T_Pray AS T WHERE 2>(SELECT COUNT(*) FROM T_Pray WHERE UserId=T.UserId AND Id>T.Id)
SELECT * FROM T_Pray AS T WHERE 1>(SELECT COUNT(*) FROM T_Pray WHERE UserId=T.UserId AND Id>T.Id)
取的是每用userid下一条
SELECT * FROM T_Pray AS T WHERE 3>(SELECT COUNT(*) FROM T_Pray WHERE UserId=T.UserId AND Id>T.Id)
取的是每个userid下三条,依此类推
写法二
SELECT * FROM T_Pray T
WHERE Id in (
SELECT top 2 Id FROM T_Pray
WHERE UserId=T.UserId order by Id asc )这样取的是每个用户最大的二个id,(含只用一条记录的)

SELECT * FROM T_Pray T
WHERE Id in (
SELECT top 1 Id FROM T_Pray
WHERE UserId=T.UserId order by Id asc )
这样取的是每个用户最大的一个id,相当于按UserId分组,取最大的一条
写法三
Select *

From

(Select *,

Row_Number() over(Partition By UserId Order by Id Asc) RowID

From T_Pray

) t WHERE t.RowID=1

这个同上面的效果,但是是sql server 特有的写法,不推荐
SELECT DISTINCT b.*
FROM T_Pray AS a
CROSS APPLY
(
SELECT TOP(2) * FROM T_Pray WHERE a.UserId=UserId ORDER BY Id DESC
) AS b
ORDER BY b.UserId这也是sql server 特有的
写法四
选取ID最前面的一条
select * from T_Pray where Id in(select min(Id) from T_Pray group by UserId)
选取ID最后面的一条
select * from T_Pray where Id in(select max(Id) from T_Pray group by UserId)这种写法也依赖于sql server的min,max函数

写法五
Select * from T_Pray a where not exists(select 1 from T_Pray where UserId=a.UserId and ID>a.ID)
类似于写法一,但这样只能取第个分类下一条,ID>a.ID 取的是最大的那条,ID<a.ID就是取的最小的那条

各写法的具体执行效率可以查询分析器里运行看到,
写法一,二的效率一般,都略低,
写法四的较好,但写法四如果max(id)不唯一时每个userid的记录不只一条
写法三第一种尚可,第二种相对要慢不少
写法五同写法一差不多