SQL Server Rank()按日期、分组和联接两个表,包括分页

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

在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        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
子句和东西简单得多。谢谢:)