按另一个相关行的值分区
partition by values from another related row
我正在尝试为每个帐户识别 table 中的最新合并交易。此 table 填充了帐户合并,最新的合并交易是较大的 merge_tx_id
来源table:
| merge_tx_id | merge_from_id | merge_to_id |
|-------------|---------------|-------------|
| 1 | 546 | 100 |
| 2 | 789 | 802 |
| 3 | 123 | 456 |
| 33 | 456 | 123 |
| 222 | 802 | 789 |
| 333 | 123 | 456 |
merge_tx_id IN (3,33,333) 是基于出现在另一行中的 merge_from_id 或 merge_to_id 的同一帐户,在此示例中执行了合并,然后 'unmerged' 稍后再说。最新的 id 应该是 '456'
| merge_tx_id | merge_from_id | merge_to_id |
|-------------|---------------|-------------|
| 3 | 123 | 456 |
| 33 | 456 | 123 |
| 333 | 123 | 456 |
merge_tx_id IN (2,222) 是同一个帐号,根据另一行出现的merge_from_id或merge_to_id,最新的是'789'
| merge_tx_id | merge_from_id | merge_to_id |
|-------------|---------------|-------------|
| 2 | 789 | 802 |
| 222 | 802 | 789 |
merge_tx_id IN (1) 与任何其他行无关,最新 ID 为“100”
| merge_tx_id | merge_from_id | merge_to_id |
|-------------|---------------|-------------|
| 1 | 546 | 100 |
我认为我需要将 table 加入自身并执行 RANK,但我不清楚如果可以的话,如何对其执行分区(第 1 列或第 2 列)。
想要的结果是
| merge_tx_id | merge_from_id | merge_to_id |
|-------------|---------------|-------------|
| 1 | 546 | 100 |
| 333 | 123 | 456 |
| 222 | 802 | 789 |
您可以使用以下查询:
SELECT merge_tx_id, merge_from_id, merge_to_id
FROM (
SELECT merge_tx_id, merge_from_id, merge_to_id,
ROW_NUMBER() OVER (PARTITION BY x.merge1, y.merge2
ORDER BY merge_tx_id DESC) AS rn
FROM merge_grp
CROSS APPLY (SELECT CASE WHEN merge_from_id < merge_to_id
THEN merge_from_id
ELSE merge_to_id
END AS merge1) AS x
CROSS APPLY (SELECT CASE WHEN merge_from_id >= merge_to_id
THEN merge_from_id
ELSE merge_to_id
END AS merge2) AS y ) t
WHERE t.rn = 1
查询使用了两个 CROSS APPLY
子句,以便将 merge_from_id
、merge_to_id
重新排列为两个等效列,merge1
、merge2
,这是按升序排列的。 ROW_NUMBER
使用这两个计算列对行进行分区,因此可以选择每个 merge1
、merge2
.
具有最大值 merge_tx_id
的行
我正在尝试为每个帐户识别 table 中的最新合并交易。此 table 填充了帐户合并,最新的合并交易是较大的 merge_tx_id
来源table:
| merge_tx_id | merge_from_id | merge_to_id |
|-------------|---------------|-------------|
| 1 | 546 | 100 |
| 2 | 789 | 802 |
| 3 | 123 | 456 |
| 33 | 456 | 123 |
| 222 | 802 | 789 |
| 333 | 123 | 456 |
merge_tx_id IN (3,33,333) 是基于出现在另一行中的 merge_from_id 或 merge_to_id 的同一帐户,在此示例中执行了合并,然后 'unmerged' 稍后再说。最新的 id 应该是 '456'
| merge_tx_id | merge_from_id | merge_to_id |
|-------------|---------------|-------------|
| 3 | 123 | 456 |
| 33 | 456 | 123 |
| 333 | 123 | 456 |
merge_tx_id IN (2,222) 是同一个帐号,根据另一行出现的merge_from_id或merge_to_id,最新的是'789'
| merge_tx_id | merge_from_id | merge_to_id |
|-------------|---------------|-------------|
| 2 | 789 | 802 |
| 222 | 802 | 789 |
merge_tx_id IN (1) 与任何其他行无关,最新 ID 为“100”
| merge_tx_id | merge_from_id | merge_to_id |
|-------------|---------------|-------------|
| 1 | 546 | 100 |
我认为我需要将 table 加入自身并执行 RANK,但我不清楚如果可以的话,如何对其执行分区(第 1 列或第 2 列)。
想要的结果是
| merge_tx_id | merge_from_id | merge_to_id |
|-------------|---------------|-------------|
| 1 | 546 | 100 |
| 333 | 123 | 456 |
| 222 | 802 | 789 |
您可以使用以下查询:
SELECT merge_tx_id, merge_from_id, merge_to_id
FROM (
SELECT merge_tx_id, merge_from_id, merge_to_id,
ROW_NUMBER() OVER (PARTITION BY x.merge1, y.merge2
ORDER BY merge_tx_id DESC) AS rn
FROM merge_grp
CROSS APPLY (SELECT CASE WHEN merge_from_id < merge_to_id
THEN merge_from_id
ELSE merge_to_id
END AS merge1) AS x
CROSS APPLY (SELECT CASE WHEN merge_from_id >= merge_to_id
THEN merge_from_id
ELSE merge_to_id
END AS merge2) AS y ) t
WHERE t.rn = 1
查询使用了两个 CROSS APPLY
子句,以便将 merge_from_id
、merge_to_id
重新排列为两个等效列,merge1
、merge2
,这是按升序排列的。 ROW_NUMBER
使用这两个计算列对行进行分区,因此可以选择每个 merge1
、merge2
.
merge_tx_id
的行