确定列是增加还是减少
Determine if column is increasing or decreasing
我有数据 table,其中的列 ORDER
应该指示值是增加还是减少,还有另一列 ORDER_BASIS
。但是,ORDER
中的数据通常一开始就不正确,因此我尝试使用 ORDER_BASIS
.
来确定正确的顺序
这是 table 的样子:
订购
ORDER_BASIS
增加
8
增加
16
增加
12
增加
5
增加
1
增加
1
增加
10
增加
16
增加
16
我正在努力实现这个目标:
订购
ORDER_BASIS
CORRECT_ORDER
增加
8
增加
增加
16
增加
增加
12
减少
增加
5
减少
增加
1
减少
增加
1
减少
增加
10
增加
增加
16
增加
增加
16
增加
第一列可以使用 ORDER
然后接下来的行应该确定它是增加还是减少。如果值没有增加或减少,则保持当前状态,直到值发生变化。
我当前的逻辑使用 LAG 和 LEAD:
SELECT
LEAD (ORDER_BASIS, 1, 0) AS NEXT_BASIS,
LAG (ORDER_BASIS, 1, 0) AS PREV_BASIS
FROM
DATA_TABLE
然后创建了一个条件但无法使其正常工作
CASE
WHEN CAST(PREV_BASIS AS int) = 0
OR (CAST(PREV_BASIS AS int) >= CAST(ORDER_BASIS AS int)
AND CAST(NEXT_BASIS AS int) <= CAST(ORDER_BASIS AS int))
THEN ORDER_BASIS
ELSE 'OPPOSITE_DIRECTION'
END AS CORRECT_ORDER
使用 SQL 服务器 2014
如果您的查询没有任何 order by
语句,行的顺序在任何时候都是完全随机的,并且可以不同。所以要解决这个问题,你需要一些可以保证行的初始顺序的列,然后我们就可以解决这个问题:
select * ,
case when ORDER_BASIS > LAG(ORDER_BASIS,1,-1) over (order by <the column>)
then 'INCREASING'
case when ORDER_BASIS = LAG(ORDER_BASIS,1,-1) over (order by <the column>)
then 'No change'
else 'DECREASING' end CORRECT_ORDER
from DATA_TABLE
对于顺序处理函数,如 LAG
和 LEAD
,顺序是最重要的维护因素,也是原始 post 中遗漏的一项。在 SQL 服务器中,window 函数将根据自己的分区(分组)和排序标准进行操作,因此在视觉上关联数据时,在外部查询中使用与您为window 函数。
The following solution can be explored in this fiddle: http://sqlfiddle.com/#!18/5e1ee/31
为了验证您的输入条件,运行 输出 LAG
和 LEAD
结果的查询:
SELECT
[Id],[Order]
, LAG (ORDER_BASIS, 1, NULL) OVER (ORDER BY [Id]) AS PREV_BASIS
, [Order_Basis]
, LEAD (ORDER_BASIS, 1, NULL) OVER (ORDER BY [Id]) AS NEXT_BASIS
FROM DATA_TABLE;
Id
Order
PREV_BASIS
Order_Basis
NEXT_BASIS
1
INCREASING
(null)
8
16
2
INCREASING
8
16
12
3
INCREASING
16
12
5
4
INCREASING
12
5
1
5
INCREASING
5
1
1
6
INCREASING
1
1
10
7
INCREASING
1
10
16
8
INCREASING
10
16
16
9
INCREASING
16
16
(null)
下一个问题是您尝试的逻辑使用 LAG
AND LEAD
值,这不是无效的,但通常用于计算一个 平滑曲线 或试图检测 尖峰 或 高点 和 低点.
It is not necessary to do this via a CTE however, it simplifies the readability of the syntax for this discussion, within the CTE we can perform the Integer Casting as well, however in a production environment it might be optimal to store the ORDER_BASIS
column as an Integer in the first place.
WITH Records as
(
SELECT
[Id],[Order]
, CAST(LAG (ORDER_BASIS, 1, NULL) OVER (ORDER BY [Id]) AS INT) AS PREV_BASIS
, CAST([Order_Basis] AS INT) AS [Order_Basis]
, CAST(LEAD (ORDER_BASIS, 1, NULL) OVER (ORDER BY [Id]) AS INT) AS NEXT_BASIS
FROM DATA_TABLE
)
SELECT
[Id],[Order],PREV_BASIS,[Order_Basis],NEXT_BASIS
,CASE
WHEN NEXT_BASIS > ORDER_BASIS AND PREV_BASIS > ORDER_BASIS THEN 'LOW'
WHEN NEXT_BASIS < ORDER_BASIS AND PREV_BASIS < ORDER_BASIS THEN 'HIGH'
WHEN ISNULL(PREV_BASIS, ORDER_BASIS) = ORDER_BASIS THEN 'NO CHANGE'
WHEN ISNULL(PREV_BASIS, ORDER_BASIS) >= ORDER_BASIS
AND ISNULL(NEXT_BASIS, ORDER_BASIS) <= ORDER_BASIS
THEN 'DECREASING'
WHEN ISNULL(PREV_BASIS, ORDER_BASIS) <= ORDER_BASIS
AND ISNULL(NEXT_BASIS, ORDER_BASIS) >= ORDER_BASIS
THEN 'INCREASING'
ELSE 'INDETERMINATE'
END AS CORRECT_ORDER
FROM Records
ORDER BY [Id];
Id
Order
PREV_BASIS
Order_Basis
NEXT_BASIS
CORRECT_ORDER
1
INCREASING
(null)
8
16
NO CHANGE
2
INCREASING
8
16
12
HIGH
3
INCREASING
16
12
5
DECREASING
4
INCREASING
12
5
1
DECREASING
5
INCREASING
5
1
1
DECREASING
6
INCREASING
1
1
10
NO CHANGE
7
INCREASING
1
10
16
INCREASING
8
INCREASING
10
16
16
INCREASING
9
INCREASING
16
16
(null)
NO CHANGE
您可以通过再次使用 LAG
比较来扩展它,以确定上述记录集中间的 NO CHANGE
实际上是否是较长时间的低点期间。
如果CORRECT ORDER
只是前一条记录的函数,那么根本不需要使用LEAD
求值:
WITH Records as
(
SELECT
[ID],[ORDER]
, CAST(LAG (ORDER_BASIS, 1, NULL) OVER (ORDER BY [Id]) AS INT) AS PREV_BASIS
, CAST([ORDER_BASIS] AS INT) AS [ORDER_BASIS]
FROM DATA_TABLE
)
SELECT
[ID],[ORDER],[PREV_BASIS],[ORDER_BASIS]
, CASE WHEN ORDER_BASIS < PREV_BASIS
THEN 'DECREASING'
WHEN ORDER_BASIS > PREV_BASIS
THEN 'INCREASING'
ELSE 'NO CHANGE'
END CORRECT_ORDER
FROM Records;
ID
ORDER
PREV_BASIS
ORDER_BASIS
CORRECT_ORDER
1
INCREASING
(null)
8
NO CHANGE
2
INCREASING
8
16
INCREASING
3
INCREASING
16
12
DECREASING
4
INCREASING
12
5
DECREASING
5
INCREASING
5
1
DECREASING
6
INCREASING
1
1
NO CHANGE
7
INCREASING
1
10
INCREASING
8
INCREASING
10
16
INCREASING
9
INCREASING
16
16
NO CHANGE
我有数据 table,其中的列 ORDER
应该指示值是增加还是减少,还有另一列 ORDER_BASIS
。但是,ORDER
中的数据通常一开始就不正确,因此我尝试使用 ORDER_BASIS
.
这是 table 的样子:
订购 | ORDER_BASIS |
---|---|
增加 | 8 |
增加 | 16 |
增加 | 12 |
增加 | 5 |
增加 | 1 |
增加 | 1 |
增加 | 10 |
增加 | 16 |
增加 | 16 |
我正在努力实现这个目标:
订购 | ORDER_BASIS | CORRECT_ORDER |
---|---|---|
增加 | 8 | 增加 |
增加 | 16 | 增加 |
增加 | 12 | 减少 |
增加 | 5 | 减少 |
增加 | 1 | 减少 |
增加 | 1 | 减少 |
增加 | 10 | 增加 |
增加 | 16 | 增加 |
增加 | 16 | 增加 |
第一列可以使用 ORDER
然后接下来的行应该确定它是增加还是减少。如果值没有增加或减少,则保持当前状态,直到值发生变化。
我当前的逻辑使用 LAG 和 LEAD:
SELECT
LEAD (ORDER_BASIS, 1, 0) AS NEXT_BASIS,
LAG (ORDER_BASIS, 1, 0) AS PREV_BASIS
FROM
DATA_TABLE
然后创建了一个条件但无法使其正常工作
CASE
WHEN CAST(PREV_BASIS AS int) = 0
OR (CAST(PREV_BASIS AS int) >= CAST(ORDER_BASIS AS int)
AND CAST(NEXT_BASIS AS int) <= CAST(ORDER_BASIS AS int))
THEN ORDER_BASIS
ELSE 'OPPOSITE_DIRECTION'
END AS CORRECT_ORDER
使用 SQL 服务器 2014
如果您的查询没有任何 order by
语句,行的顺序在任何时候都是完全随机的,并且可以不同。所以要解决这个问题,你需要一些可以保证行的初始顺序的列,然后我们就可以解决这个问题:
select * ,
case when ORDER_BASIS > LAG(ORDER_BASIS,1,-1) over (order by <the column>)
then 'INCREASING'
case when ORDER_BASIS = LAG(ORDER_BASIS,1,-1) over (order by <the column>)
then 'No change'
else 'DECREASING' end CORRECT_ORDER
from DATA_TABLE
对于顺序处理函数,如 LAG
和 LEAD
,顺序是最重要的维护因素,也是原始 post 中遗漏的一项。在 SQL 服务器中,window 函数将根据自己的分区(分组)和排序标准进行操作,因此在视觉上关联数据时,在外部查询中使用与您为window 函数。
The following solution can be explored in this fiddle: http://sqlfiddle.com/#!18/5e1ee/31
为了验证您的输入条件,运行 输出 LAG
和 LEAD
结果的查询:
SELECT
[Id],[Order]
, LAG (ORDER_BASIS, 1, NULL) OVER (ORDER BY [Id]) AS PREV_BASIS
, [Order_Basis]
, LEAD (ORDER_BASIS, 1, NULL) OVER (ORDER BY [Id]) AS NEXT_BASIS
FROM DATA_TABLE;
Id | Order | PREV_BASIS | Order_Basis | NEXT_BASIS |
---|---|---|---|---|
1 | INCREASING | (null) | 8 | 16 |
2 | INCREASING | 8 | 16 | 12 |
3 | INCREASING | 16 | 12 | 5 |
4 | INCREASING | 12 | 5 | 1 |
5 | INCREASING | 5 | 1 | 1 |
6 | INCREASING | 1 | 1 | 10 |
7 | INCREASING | 1 | 10 | 16 |
8 | INCREASING | 10 | 16 | 16 |
9 | INCREASING | 16 | 16 | (null) |
下一个问题是您尝试的逻辑使用 LAG
AND LEAD
值,这不是无效的,但通常用于计算一个 平滑曲线 或试图检测 尖峰 或 高点 和 低点.
It is not necessary to do this via a CTE however, it simplifies the readability of the syntax for this discussion, within the CTE we can perform the Integer Casting as well, however in a production environment it might be optimal to store the
ORDER_BASIS
column as an Integer in the first place.
WITH Records as
(
SELECT
[Id],[Order]
, CAST(LAG (ORDER_BASIS, 1, NULL) OVER (ORDER BY [Id]) AS INT) AS PREV_BASIS
, CAST([Order_Basis] AS INT) AS [Order_Basis]
, CAST(LEAD (ORDER_BASIS, 1, NULL) OVER (ORDER BY [Id]) AS INT) AS NEXT_BASIS
FROM DATA_TABLE
)
SELECT
[Id],[Order],PREV_BASIS,[Order_Basis],NEXT_BASIS
,CASE
WHEN NEXT_BASIS > ORDER_BASIS AND PREV_BASIS > ORDER_BASIS THEN 'LOW'
WHEN NEXT_BASIS < ORDER_BASIS AND PREV_BASIS < ORDER_BASIS THEN 'HIGH'
WHEN ISNULL(PREV_BASIS, ORDER_BASIS) = ORDER_BASIS THEN 'NO CHANGE'
WHEN ISNULL(PREV_BASIS, ORDER_BASIS) >= ORDER_BASIS
AND ISNULL(NEXT_BASIS, ORDER_BASIS) <= ORDER_BASIS
THEN 'DECREASING'
WHEN ISNULL(PREV_BASIS, ORDER_BASIS) <= ORDER_BASIS
AND ISNULL(NEXT_BASIS, ORDER_BASIS) >= ORDER_BASIS
THEN 'INCREASING'
ELSE 'INDETERMINATE'
END AS CORRECT_ORDER
FROM Records
ORDER BY [Id];
Id | Order | PREV_BASIS | Order_Basis | NEXT_BASIS | CORRECT_ORDER |
---|---|---|---|---|---|
1 | INCREASING | (null) | 8 | 16 | NO CHANGE |
2 | INCREASING | 8 | 16 | 12 | HIGH |
3 | INCREASING | 16 | 12 | 5 | DECREASING |
4 | INCREASING | 12 | 5 | 1 | DECREASING |
5 | INCREASING | 5 | 1 | 1 | DECREASING |
6 | INCREASING | 1 | 1 | 10 | NO CHANGE |
7 | INCREASING | 1 | 10 | 16 | INCREASING |
8 | INCREASING | 10 | 16 | 16 | INCREASING |
9 | INCREASING | 16 | 16 | (null) | NO CHANGE |
您可以通过再次使用 LAG
比较来扩展它,以确定上述记录集中间的 NO CHANGE
实际上是否是较长时间的低点期间。
如果CORRECT ORDER
只是前一条记录的函数,那么根本不需要使用LEAD
求值:
WITH Records as
(
SELECT
[ID],[ORDER]
, CAST(LAG (ORDER_BASIS, 1, NULL) OVER (ORDER BY [Id]) AS INT) AS PREV_BASIS
, CAST([ORDER_BASIS] AS INT) AS [ORDER_BASIS]
FROM DATA_TABLE
)
SELECT
[ID],[ORDER],[PREV_BASIS],[ORDER_BASIS]
, CASE WHEN ORDER_BASIS < PREV_BASIS
THEN 'DECREASING'
WHEN ORDER_BASIS > PREV_BASIS
THEN 'INCREASING'
ELSE 'NO CHANGE'
END CORRECT_ORDER
FROM Records;
ID | ORDER | PREV_BASIS | ORDER_BASIS | CORRECT_ORDER |
---|---|---|---|---|
1 | INCREASING | (null) | 8 | NO CHANGE |
2 | INCREASING | 8 | 16 | INCREASING |
3 | INCREASING | 16 | 12 | DECREASING |
4 | INCREASING | 12 | 5 | DECREASING |
5 | INCREASING | 5 | 1 | DECREASING |
6 | INCREASING | 1 | 1 | NO CHANGE |
7 | INCREASING | 1 | 10 | INCREASING |
8 | INCREASING | 10 | 16 | INCREASING |
9 | INCREASING | 16 | 16 | NO CHANGE |