SQL Server Rank()按日期、分组和联接两个表,包括分页
在SQL Server中有这两个表: 购物车:SQL Server Rank()按日期、分组和联接两个表,包括分页,sql,sql-server,database,tsql,group-by,Sql,Sql Server,Database,Tsql,Group By,在SQL Server中有这两个表: 购物车: id userid prodid qt date 1 21 P1 1 2017-02-18 2 21 P8 1 2017-02-19 3 21 P2 1 2017-02-20 4 22 P5 1 2017-02-21 5 22 P
id userid prodid qt date
1 21 P1 1 2017-02-18
2 21 P8 1 2017-02-19
3 21 P2 1 2017-02-20
4 22 P5 1 2017-02-21
5 22 P3 1 2017-02-22
6 23 P4 1 2017-02-23
id user_name
21 John
22 James
23 Alice
24 Lily
用户:
id userid prodid qt date
1 21 P1 1 2017-02-18
2 21 P8 1 2017-02-19
3 21 P2 1 2017-02-20
4 22 P5 1 2017-02-21
5 22 P3 1 2017-02-22
6 23 P4 1 2017-02-23
id user_name
21 John
22 James
23 Alice
24 Lily
我想要一个表,其中只显示最新日期的文章,按用户id分组,有1列(art_c),每个用户添加到购物车的文章数量(不是Qt,即数量),并与用户表连接。
另外,我想为结果的每一行添加分页
我想要的结果如下:
id userid user_name prodid art_c date
3 21 John P2 3 2017-02-20
5 22 James P3 2 2017-02-22
6 23 Alice P4 1 2017-02-23
这样做的最佳/最快方法是什么?
我正在使用此请求,我不确定这是否是一个好的/快速的方法:
With tb_a as
(
SELECT u_id,u_name,dat,art_c,ROW_NUMBER() OVER (ORDER BY u_name) as rgw FROM
shopcart a
LEFT JOIN
(SELECT
a.userid as u_id,
b.user_name as u_name,
Format(shop_date, 'dd.MM.yyyy HH:mm') as dat,
RANK() OVER (PARTITION BY a.userid ORDER BY shop_date DESC) as dest_rank,
Count(a.id) OVER (PARTITION BY a.userid ORDER BY shop_date) as art_c
FROM
shopcart a
LEFT JOIN
Users b on a.userid=b.id
group by
a.userid,b.name,shop_date,a.id) b on a.userid=b.u_id
where dest_rank = 1
group by u_id,u_name,dat,art_c
)
SELECT * FROM tb_a
WHERE rgw BETWEEN 0 AND 100 order by rgw
我想你只需要在
购物车上使用行号()。在加入之前,我会这样做:
select u.*, sc.*
from (select sc.*,
row_number() over (partition by sc.userid order by date desc) as seqnum
from ShopCart sc
) sc join
users u
on sc.userid = u.id
where seqnum = 1;
对于分页,您可以添加order by
,然后可以使用offset
和fetch next
编辑:
您也可以使用窗口函数获取计数:
select u.*, sc.*
from (select sc.*,
row_number() over (partition by sc.userid order by date desc) as seqnum,
count(*) over (partition by sc.userid) as cnt
from ShopCart sc
) sc join
users u
on sc.userid = u.id
where seqnum = 1;
我想你只需要在购物车上使用行号()。在加入之前,我会这样做:
select u.*, sc.*
from (select sc.*,
row_number() over (partition by sc.userid order by date desc) as seqnum
from ShopCart sc
) sc join
users u
on sc.userid = u.id
where seqnum = 1;
对于分页,您可以添加order by
,然后可以使用offset
和fetch next
编辑:
您也可以使用窗口函数获取计数:
select u.*, sc.*
from (select sc.*,
row_number() over (partition by sc.userid order by date desc) as seqnum,
count(*) over (partition by sc.userid) as cnt
from ShopCart sc
) sc join
users u
on sc.userid = u.id
where seqnum = 1;
与语句和行号一起使用,如下所示,PartNo列将按用户ID对数据进行分组,SeqNo列获取用户计数:
;WITH S AS
(
SELECT
*,
COUNT(Id) OVER (PARTITION BY UserId) AS PartNo,
ROW_NUMBER() OVER (PARTITION BY UserId Order BY Date DESC) AS SeqNo
FROM @ShopCart SC
)
SELECT
S.Id,
S.UserId,
U.UserName ,
S.ProdId,
S.PartNo AS Art_c,
S.Date
FROM S
LEFT JOIN @User U ON S.UserId=U.Id
WHERE S.SeqNo=1
与语句和行号一起使用,如下所示,PartNo列将按用户ID对数据进行分组,SeqNo列获取用户计数:
;WITH S AS
(
SELECT
*,
COUNT(Id) OVER (PARTITION BY UserId) AS PartNo,
ROW_NUMBER() OVER (PARTITION BY UserId Order BY Date DESC) AS SeqNo
FROM @ShopCart SC
)
SELECT
S.Id,
S.UserId,
U.UserName ,
S.ProdId,
S.PartNo AS Art_c,
S.Date
FROM S
LEFT JOIN @User U ON S.UserId=U.Id
WHERE S.SeqNo=1
如果您担心速度,建议不要使用FORMAT()
当一个用户的两个产品的最新日期相同时,该怎么办?@ThorstenKettner这只是一个示例,在DB中,我有一个精确到miliseconds@mendosi谢谢,我不知道FORMAT()
如果您关心速度,建议不要使用FORMAT()
当一个用户有两个具有相同最新日期的产品时该怎么办?@ThorstenKettner这只是一个示例,在DB中,我有一个精确到miliseconds@mendosi谢谢,我不知道FORMAT()
非常好而且干净的解决方案。(如果您觉得这更具可读性,您可以用COUNT(*)OVER(PARTITION BY UserId Order BY Date)
替换ROW_NUMBER()(PARTITION BY UserId)
。@ThorstenKettner此解决方案和您的解决方案正在运行,并给出我想要的结果,但执行计划不同。我不知道哪个更好,我也不知道,但戈登和桑迪普的查询速度可能比我的快。他们只看了一次表。非常好而且干净的解决方案。(如果您觉得这更具可读性,您可以用COUNT(*)OVER(PARTITION BY UserId Order BY Date)
替换ROW_NUMBER()(PARTITION BY UserId)
。@ThorstenKettner此解决方案和您的解决方案正在运行,并给出我想要的结果,但执行计划不同。我不知道哪个更好,我也不知道,但戈登和桑迪普的查询速度可能比我的快。他们只看了一次桌子。谢谢!您认为,offset
和fetch next
比使用ROW\u NUMBER()。我会使用OFFSET
和fetchnext
。它们是为分页而设计的,真神奇!非常感谢。这种分页方法也很棒。奇怪,但我不知道。编写OFFSET
和FETCH
要比使用WITH
子句和东西简单得多。谢谢:)谢谢!您认为,offset
和fetch next
比使用ROW\u NUMBER()。我会使用OFFSET
和fetchnext
。它们是为分页而设计的,真神奇!非常感谢。这种分页方法也很棒。奇怪,但我不知道。编写OFFSET
和FETCH
要比使用WITH
子句和东西简单得多。谢谢:)