根据条件对结果集进行排序
Rank result set according to condition
我有一个 table,它有 3 列:产品、日期、状态
我想这样排名:
对于按日期排列的每个产品订单,如果 Status = FALSE 则排名为 0,如果为 TRUE,则从 1 开始排名,如果之前的 Status 为 TRUE,则继续按相同的值排名。
在这个有序集合中,如果 FALSE 出现,则分配给它 0,对于同一产品的下一个 TRUE 状态,分配 x+1(这里的 x 是状态 TRUE 的先前排名值)。
希望图片更清楚
试试这个查询,
SELECT a.Product ,
a.Date ,
a.Status ,
CASE WHEN a.Status = 'FALSE' THEN 0
ELSE 1
END [Rank]
FROM ( SELECT 产品 ,
日期 ,
状态 ,
ROW_NUMBER() OVER ( PARTITION BY Product ORDER BY DATE, Status ) RNK
FROM 表产品
) 一种
按产品排序,a.RNK
此代码使用不包含 LEAD
/LAG
的 SS2008R2 功能。使用更现代版本的 SQL 服务器当然可以有更好的解决方案。
-- Sample data.
declare @Samples as Table ( Product VarChar(10), ProductDate Date,
ProductStatus Bit, DesiredRank Int );
insert into @Samples values
( 'a', '20160525', 0, 0 ), ( 'a', '20160526', 1, 1 ), ( 'a', '20160529', 1, 1 ),
( 'a', '20160601', 1, 1 ), ( 'a', '20160603', 0, 0 ), ( 'a', '20160604', 0, 0 ),
( 'a', '20160611', 1, 2 ), ( 'a', '20160612', 0, 0 ), ( 'a', '20160613', 1, 3 ),
( 'b', '20160521', 1, 1 ), ( 'b', '20160522', 0, 0 ), ( 'b', '20160525', 1, 2 );
select * from @Samples;
-- Query to rank data as requested.
with WithRN as (
select Product, ProductDate, ProductStatus, DesiredRank,
Row_Number() over ( partition by Product order by ProductDate ) as RN
from @Samples
),
RCTE as (
select *, Cast( ProductStatus as Int ) as C
from WithRN
where RN = 1
union all
select WRN.*, C + Cast( 1 - R.ProductStatus as Int ) * Cast( WRN.ProductStatus as Int )
from RCTE as R inner join
WithRN as WRN on WRN.Product = R.Product and WRN.RN = R.RN + 1 )
select Product, ProductDate, ProductStatus, DesiredRank,
C * ProductStatus as CalculatedRank
from RCTE
order by Product, ProductDate;
请注意,示例数据是使用 Mark I Eyeball 从图像中提取的。如果 OP 听取了建议 here 它会更容易一些。
提示:使用与数据类型和关键字不匹配的列名可以让事情变得更简单。
我有一个 table,它有 3 列:产品、日期、状态
我想这样排名: 对于按日期排列的每个产品订单,如果 Status = FALSE 则排名为 0,如果为 TRUE,则从 1 开始排名,如果之前的 Status 为 TRUE,则继续按相同的值排名。
在这个有序集合中,如果 FALSE 出现,则分配给它 0,对于同一产品的下一个 TRUE 状态,分配 x+1(这里的 x 是状态 TRUE 的先前排名值)。
希望图片更清楚
试试这个查询,
SELECT a.Product ,
a.Date ,
a.Status ,
CASE WHEN a.Status = 'FALSE' THEN 0
ELSE 1
END [Rank]
FROM ( SELECT 产品 , 日期 , 状态 , ROW_NUMBER() OVER ( PARTITION BY Product ORDER BY DATE, Status ) RNK FROM 表产品 ) 一种 按产品排序,a.RNK
此代码使用不包含 LEAD
/LAG
的 SS2008R2 功能。使用更现代版本的 SQL 服务器当然可以有更好的解决方案。
-- Sample data.
declare @Samples as Table ( Product VarChar(10), ProductDate Date,
ProductStatus Bit, DesiredRank Int );
insert into @Samples values
( 'a', '20160525', 0, 0 ), ( 'a', '20160526', 1, 1 ), ( 'a', '20160529', 1, 1 ),
( 'a', '20160601', 1, 1 ), ( 'a', '20160603', 0, 0 ), ( 'a', '20160604', 0, 0 ),
( 'a', '20160611', 1, 2 ), ( 'a', '20160612', 0, 0 ), ( 'a', '20160613', 1, 3 ),
( 'b', '20160521', 1, 1 ), ( 'b', '20160522', 0, 0 ), ( 'b', '20160525', 1, 2 );
select * from @Samples;
-- Query to rank data as requested.
with WithRN as (
select Product, ProductDate, ProductStatus, DesiredRank,
Row_Number() over ( partition by Product order by ProductDate ) as RN
from @Samples
),
RCTE as (
select *, Cast( ProductStatus as Int ) as C
from WithRN
where RN = 1
union all
select WRN.*, C + Cast( 1 - R.ProductStatus as Int ) * Cast( WRN.ProductStatus as Int )
from RCTE as R inner join
WithRN as WRN on WRN.Product = R.Product and WRN.RN = R.RN + 1 )
select Product, ProductDate, ProductStatus, DesiredRank,
C * ProductStatus as CalculatedRank
from RCTE
order by Product, ProductDate;
请注意,示例数据是使用 Mark I Eyeball 从图像中提取的。如果 OP 听取了建议 here 它会更容易一些。
提示:使用与数据类型和关键字不匹配的列名可以让事情变得更简单。