首页 > 解决方案 > 查询:如何根据条件枚举行?

问题描述

有下表:

DROP TABLE IF EXISTS #Data
CREATE TABLE #Data
(
    Code VARCHAR(10),
    Fee VARCHAR(3),
    AValue DECIMAL(10, 4)
)
-- DELETE FROM #Data
INSERT INTO #Data
VALUES
('A001', '001', 100), ('A001', '002', 200), ('A001', '003', -50), ('A001', '004', -250), ('A001', '005', 340), ('A001', '006', 500), ('A001', '007', 600)

我需要得到以下结果(基于 Value 仍然是正数还是负数的有序序列):

Code    Fee Value      Row
A001    001 100.0000   P1
A001    002 200.0000   P1
A001    003 -50.0000   N1
A001    004 -250.0000  N1
A001    005 340.0000   P2
A001    006 500.0000   P2
A001    007 600.0000   P2

我试过这个:

SELECT Code, Fee, AValue, ROW_NUMBER() OVER(PARTITION BY Code, (CASE WHEN AValue > 0 THEN 1 ELSE 2 END) ORDER BY Fee) 'nRow',
FORMAT(ROW_NUMBER() OVER(PARTITION BY Code, Fee, CASE WHEN AValue > 0 THEN 1 ELSE 2 END ORDER BY Fee), CASE WHEN AValue > 0 THEN 'POS00' ELSE 'NEG00' END)
FROM #Data

但它返回:

Code    Fee Value      Row
A001    001 100.0000   P1
A001    002 200.0000   P1
A001    003 -50.0000   N1
A001    004 -250.0000  N1
A001    005 340.0000   P1

标签: sqlsql-serverperformancesql-server-2012

解决方案


这是一种差距和孤岛问题,但它很棘手。假设你没有0价值观,那么sign()就是你的朋友。

这是一种方法,当相邻行上的值应该组合时,行号的差异是恒定的:

SELECT Code, Fee, AValue, 
       DENSE_RANK() OVER (PARTITION BY sign(avalue) ORDER BY seqnum - seqnum_2) as num
FROM (SELECT d.*,
             ROW_NUMBER() OVER (PARTITION BY code, sign(avalue) ORDER BY fee) as seqnum_2,
             ROW_NUMBER() OVER (PARTITION BY code ORDER BY fee) as seqnum
      FROM Data d
     ) d
ORDER BY Code, Fee;

您可以使用CONCAT()或其他方式将其合并到您的字符串中。

是一个 db<>fiddle。


推荐阅读