根据查找表值以特殊顺序对行进行排序

问题描述 投票:0回答:1

在下面的查询中,当

DENSE_RANK() OVER (ORDER BY  m_id)
中的列是主表列之一时,我得到了我想要的结果。类似的东西

m_id m_txt s_txt s_日期 系统排名
1 第 1 项 1
2 第 2 项 子项2-3 2020年1月1日 2
2 第 2 项 子项2-2 2025 年 10 月 11 日 2
2 第 2 项 子项2-1 2023 年 7 月 1 日 2
3 第 3 项 3
4 第 4 项 子项4-3 2020年3月1日 4
4 第 4 项 子项4-2 2020年5月1日 4
4 第 4 项 子项4-1 2026 年 3 月 1 日 4

这就是我想要的,因为我想按 m_id 进行[密集]排名。最终,我会选择前10名或者21到30之间的排名来获得10件物品。 DESC 同样适用。

但是,如果我尝试从查找表中按

s_date
s_date desc
排序,这就是我遇到问题的时候。

问题 - 是否有可能得到这样的结果(如下)?在这里,我真的很关心同一 ID 下的项目被一个接一个地列出,并且在每个这样的组中,最重要的日期首先列出。?我已经无法思考,我怎样才能达到这个结果。谢谢

m_id m_txt s_txt s_日期 系统排名
4 第 4 项 子项4-1 2026 年 3 月 1 日 1
4 第 4 项 子项4-2 2020年5月1日 1
4 第 4 项 子项4-3 2020年3月1日 1
2 第 2 项 子项2-2 2025 年 10 月 11 日 2
2 第 2 项 子项2-1 2023 年 7 月 1 日 2
2 第 2 项 子项2-3 2020年1月1日 2
1 第 1 项 3
3 第 3 项 4
SELECT
   Outer_Tbl_Alias.*,
   sys___max_rank AS sys___countAllFoundRecords

FROM
(
    SELECT Rank_tbl_Alias.*,
        MAX(sys___rank) OVER() AS sys___max_rank
    FROM
    ( 
        SELECT
            Union_Tbl_Alias.*,
            DENSE_RANK() OVER (ORDER BY  m_id) AS sys___rank
        FROM
        (
SELECT 
   PerfData1.id m_id,
   PerfData1.c1 m_txt,
   PerfData2.c1 s_txt,
   PerfData2.d  s_date
FROM 
  PerfData1   left Join 
  PerfData2   On PerfData1.id = PerfData2.fkid    
WHERE (1 = 1) AND
   PerfData1.id < 200 

UNION

SELECT 
   PerfData3.id m_id,
   PerfData3.c1 m_txt,
   PerfData4.c1 s_txt,
   PerfData4.d  s_date
FROM 
  PerfData3  left Join 
  PerfData4  On PerfData3.id = PerfData4.fkid    
WHERE (1 = 1) AND
   PerfData3.id > 800

) Union_Tbl_Alias
ORDER BY
    m_id
OFFSET 0 ROWS
FETCH NEXT 950 ROWS ONLY    ) Rank_tbl_Alias
) Outer_Tbl_Alias

-- generate structure
create table PerfData1 (id int primary key, c1 varchar(100));
create table PerfData2 (id int identity primary key, fkId int, c1 varchar(100), d datetime, FOREIGN KEY (fkId) REFERENCES PerfData1(id));
create table PerfData3 (id int primary key, c1 varchar(100));
create table PerfData4 (id int identity primary key, fkId int, c1 varchar(100), d datetime, FOREIGN KEY (fkId) REFERENCES PerfData3(id));

-- generate data
DECLARE @id INTEGER = 0, @date datetime = GetDate();
begin 
    WHILE @id <= 10000
    BEGIN
        SET @id = @id + 1; 
        insert into PerfData1 (id, c1) values (@id, concat( 'item ', @id) );

        if @id % 2 = 0
        begin
            SET @date = DateAdd(minute, abs(rand() * 10000), GetDate());
            insert into PerfData2 (fkId, c1, d) values (@id, concat( 'SubItem ', @id, '-', 1), @date);
             SET @date = DateAdd(minute, abs(rand() * 100000), GetDate());
            insert into PerfData2 (fkId, c1, d) values (@id, concat( 'SubItem ', @id, '-', 2), @date);
             SET @date = DateAdd(minute, abs(rand() * 200000), GetDate());
            insert into .PerfData2 (fkId, c1, d) values (@id, concat( 'SubItem ', @id, '-', 3), @date);
        end;
    END;
end;
sql sql-server
1个回答
0
投票

你可以这样做:

with
q as (
  select * from t
),
r as (
  select x.*, row_number() over(order by md desc, sys_rank) as new_rank
  from (
    select sys_rank, max(s_date) as md from q group by sys_rank
  ) x
)
select q.*, r.new_rank
from q
join r on r.sys_rank = q.sys_rank
order by r.new_rank, q.s_date desc

结果:

 m_id  m_txt   s_txt        s_date      sys_rank  new_rank 
 ----- ------- ------------ ----------- --------- -------- 
 4     item 4  SubItem 4-1  2026-03-01  4         1        
 4     item 4  SubItem 4-2  2020-05-01  4         1        
 4     item 4  SubItem 4-3  2020-03-01  4         1        
 2     item 2  SubItem 2-2  2025-10-11  2         2        
 2     item 2  SubItem 2-1  2023-07-01  2         2        
 2     item 2  SubItem 2-3  2020-01-01  2         2        
 1     item 1  null         null        1         3        
 3     item 3  null         null        3         4        

请参阅 db<>fiddle 处的运行示例。

© www.soinside.com 2019 - 2024. All rights reserved.