在不破坏序列的情况下对列进行分组
Grouping Column Without Breaking The Sequence
主要objective是将Amount列之后的行按顺序分组,这样,如果2个相同的值之间有任何不同的值,它们将被编号分别地。
这是这里的原始数据:
SELECT Area, DateA, DateB, Amount
FROM (VALUES
('ABC', '2019-08-18', '2019-08-18 00:07:47.000', 3.75),
('ABC','2019-08-19', '2019-08-19 00:08:47.000', 3.75),
('ABC','2019-08-20', '2019-08-20 00:09:47.000', 3.65),
('ABC','2019-08-21', '2019-08-21 00:09:57.000', 3.75))
AS FeeCollection(Area, DateA, DateB, Amount)
我已经试过了,但是我不知道以特殊方式编号的真正问题。
DENSE_RANK() OVER(ORDER BY Area, Amount)
这是我想要达到的示例结果。我正在寻找简单的逻辑来做到这一点。使用游标或 while 循环对我来说效率不高。
我相信这就是你想要的。我使用 LAG
获取 CTE 中前一行的值,然后使用窗口 COUNT
将具有相同连续值的每一行的 ROW_NUMBER
的值减少 1 amount
:
WITH CTE AS(
SELECT Area,
DateA,
DateB,
Amount,
LAG(Amount) OVER (PARTITION BY Area ORDER BY DateA) AS PrevAmount
FROM (VALUES
('ABC', '2019-08-18', '2019-08-18 00:07:47.000', 3.75),
('ABC','2019-08-19', '2019-08-19 00:08:47.000', 3.75),
('ABC','2019-08-20', '2019-08-20 00:09:47.000', 3.65),
('ABC','2019-08-21', '2019-08-21 00:09:57.000', 3.75))
AS FeeCollection(Area, DateA, DateB, Amount))
SELECT Area,
DateA,
DateB,
Amount,
ROW_NUMBER() OVER (PARTITION BY Area ORDER BY DateA) -
COUNT(CASE Amount WHEN PrevAmount THEN 1 END) OVER (PARTITION BY Area ORDER BY DateA
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Number
FROM CTE
ORDER BY DateA;
我确实假定了您的 PARTITION BY
子句,您可能需要 change/remove/move 到 ORDER BY
。由于我们只有一个 Area
的值,因此无法知道它更改时该值应该是什么。
我会使用 lag()
和累计总和来执行此操作,但看起来像:
select t.*,
sum(case when prev_amount = amount then 0 else 1 end) over
(partition by area order by datea) as number
from (select t.*,
lag(amount) over (partition by area order by datea) as prev_amount
from t
) t;
主要objective是将Amount列之后的行按顺序分组,这样,如果2个相同的值之间有任何不同的值,它们将被编号分别地。 这是这里的原始数据:
SELECT Area, DateA, DateB, Amount
FROM (VALUES
('ABC', '2019-08-18', '2019-08-18 00:07:47.000', 3.75),
('ABC','2019-08-19', '2019-08-19 00:08:47.000', 3.75),
('ABC','2019-08-20', '2019-08-20 00:09:47.000', 3.65),
('ABC','2019-08-21', '2019-08-21 00:09:57.000', 3.75))
AS FeeCollection(Area, DateA, DateB, Amount)
我已经试过了,但是我不知道以特殊方式编号的真正问题。
DENSE_RANK() OVER(ORDER BY Area, Amount)
这是我想要达到的示例结果。我正在寻找简单的逻辑来做到这一点。使用游标或 while 循环对我来说效率不高。
我相信这就是你想要的。我使用 LAG
获取 CTE 中前一行的值,然后使用窗口 COUNT
将具有相同连续值的每一行的 ROW_NUMBER
的值减少 1 amount
:
WITH CTE AS(
SELECT Area,
DateA,
DateB,
Amount,
LAG(Amount) OVER (PARTITION BY Area ORDER BY DateA) AS PrevAmount
FROM (VALUES
('ABC', '2019-08-18', '2019-08-18 00:07:47.000', 3.75),
('ABC','2019-08-19', '2019-08-19 00:08:47.000', 3.75),
('ABC','2019-08-20', '2019-08-20 00:09:47.000', 3.65),
('ABC','2019-08-21', '2019-08-21 00:09:57.000', 3.75))
AS FeeCollection(Area, DateA, DateB, Amount))
SELECT Area,
DateA,
DateB,
Amount,
ROW_NUMBER() OVER (PARTITION BY Area ORDER BY DateA) -
COUNT(CASE Amount WHEN PrevAmount THEN 1 END) OVER (PARTITION BY Area ORDER BY DateA
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Number
FROM CTE
ORDER BY DateA;
我确实假定了您的 PARTITION BY
子句,您可能需要 change/remove/move 到 ORDER BY
。由于我们只有一个 Area
的值,因此无法知道它更改时该值应该是什么。
我会使用 lag()
和累计总和来执行此操作,但看起来像:
select t.*,
sum(case when prev_amount = amount then 0 else 1 end) over
(partition by area order by datea) as number
from (select t.*,
lag(amount) over (partition by area order by datea) as prev_amount
from t
) t;