SQL:Select 最近的带分组的顺序不同值
SQL: Select Most Recent Sequentially Distinct Value w/ Grouping
我在编写一个查询时遇到问题,该查询将 select 最后一个 "new" 顺序不同的值(我们称此列为 Col A)基于另一列(Col B)分组。由于这有点ambiguous/confusing,这里有一个例子来解释(假设行号表示序列inside组;在我的问题中,行是按日期排序的):
|--------|-------|-------|
| RowNum | Col A | Col B |
|--------|-------|-------|
| 1 | A | A |
| 2 | B | A |
| 3 | C | A |
| 4 | B | B |
| 5 | A | B |
| 6 | B | B |
会 select:
| 3 | C | A |
| 6 | B | B |
请注意,虽然 B 也出现在第 4 行中,但第 5 行包含 A 的事实意味着第 6 行中的 B 顺序不同。但是如果 table 看起来像这样:
|--------|-------|-------|
| RowNum | Col A | Col B |
|--------|-------|-------|
| 1 | A | A |
| 2 | B | A |
| 3 | C | A |
| 4 | B | B |
| 5 | A | B |
| 6 | A | B | <--
那么我们想要select:
| 3 | C | A |
| 5 | A | B |
我认为如果我不关心值是不同的但不是顺序的,这将是一个更容易的问题。我不太确定在进行查询时如何考虑顺序。
我试图通过计算出现 Col A 的每个值的 min/max 行号来解决这个问题。该计算(使用第二个样本 table)将产生如下结果:
|--------|--------|--------|--------|
| ColA | ColB | MinRow | MaxRow |
|--------|--------|--------|--------|
| A | A | 1 | 1 |
| B | A | 2 | 2 |
| C | A | 3 | 3 |
| A | B | 5 | 6 |
| B | B | 4 | 4 |
相关 post () 中提出的解决方案走的是类似的路径,本质上是采用与上一个 ColA 不同的最新 RowNum,然后选择下一行。但是,在那个问题中,我未能解决查询对多个组起作用的需要,因此新 post。
如能在 SQL 中解决此问题,我们将不胜感激。我是 运行 SQL 2008 SP4。
嗯。 . .一种方法是获取最后一个值。然后选择具有该值的所有最后一行并聚合:
select min(rownum), colA, colB
from (select t.*,
first_value(colA) over (partition by colB order by rownum desc) as last_colA
from t
) t
where rownum > all (select t2.rownum
from t t2
where t2.colB = t.colB and t2.colA <> t.last_colA
)
group by colA, colB;
或者,没有聚合:
select t.*
from (select t.*,
first_value(colA) over (partition by colB order by rownum desc) as last_colA,
lag(colA) over (partition by colB order by rownum) as prev_clA
from t
) t
where rownum > all (select t2.rownum
from t t2
where t2.colB = t.colB and t2.colA <> t.last_colA
) and
(prev_colA is null or prev_colA <> colA);
但在 SQL Server 2008 中,我们将其视为 gaps-and-islands 问题:
select t.*
from (select t.*,
min(rownum) over (partition by colB, colA, (seqnum_b - seqnum_ab) ) as min_rownum_group,
max(rownum) over (partition by colB, colA, (seqnum_b - seqnum_ab) ) as max_rownum_group
from (select t.*,
row_number() over (partition by colB order by rownum) as seqnum_b,
row_number() over (partition by colB, colA order by rownum) as seqnum_ab,
max(rownum) over (partition by colB order by rownum) as max_rownum
from t
) t
) t
where rownum = min_rownum_group and -- first row in the group defined by adjacent colA, colB
max_rownum_group = max_rownum -- last group for each colB;
这使用不同的行号来标识每个组。它计算数据中组和整体的最大行数。这些与最后一组相同。
我在编写一个查询时遇到问题,该查询将 select 最后一个 "new" 顺序不同的值(我们称此列为 Col A)基于另一列(Col B)分组。由于这有点ambiguous/confusing,这里有一个例子来解释(假设行号表示序列inside组;在我的问题中,行是按日期排序的):
|--------|-------|-------|
| RowNum | Col A | Col B |
|--------|-------|-------|
| 1 | A | A |
| 2 | B | A |
| 3 | C | A |
| 4 | B | B |
| 5 | A | B |
| 6 | B | B |
会 select:
| 3 | C | A |
| 6 | B | B |
请注意,虽然 B 也出现在第 4 行中,但第 5 行包含 A 的事实意味着第 6 行中的 B 顺序不同。但是如果 table 看起来像这样:
|--------|-------|-------|
| RowNum | Col A | Col B |
|--------|-------|-------|
| 1 | A | A |
| 2 | B | A |
| 3 | C | A |
| 4 | B | B |
| 5 | A | B |
| 6 | A | B | <--
那么我们想要select:
| 3 | C | A |
| 5 | A | B |
我认为如果我不关心值是不同的但不是顺序的,这将是一个更容易的问题。我不太确定在进行查询时如何考虑顺序。
我试图通过计算出现 Col A 的每个值的 min/max 行号来解决这个问题。该计算(使用第二个样本 table)将产生如下结果:
|--------|--------|--------|--------|
| ColA | ColB | MinRow | MaxRow |
|--------|--------|--------|--------|
| A | A | 1 | 1 |
| B | A | 2 | 2 |
| C | A | 3 | 3 |
| A | B | 5 | 6 |
| B | B | 4 | 4 |
相关 post (
如能在 SQL 中解决此问题,我们将不胜感激。我是 运行 SQL 2008 SP4。
嗯。 . .一种方法是获取最后一个值。然后选择具有该值的所有最后一行并聚合:
select min(rownum), colA, colB
from (select t.*,
first_value(colA) over (partition by colB order by rownum desc) as last_colA
from t
) t
where rownum > all (select t2.rownum
from t t2
where t2.colB = t.colB and t2.colA <> t.last_colA
)
group by colA, colB;
或者,没有聚合:
select t.*
from (select t.*,
first_value(colA) over (partition by colB order by rownum desc) as last_colA,
lag(colA) over (partition by colB order by rownum) as prev_clA
from t
) t
where rownum > all (select t2.rownum
from t t2
where t2.colB = t.colB and t2.colA <> t.last_colA
) and
(prev_colA is null or prev_colA <> colA);
但在 SQL Server 2008 中,我们将其视为 gaps-and-islands 问题:
select t.*
from (select t.*,
min(rownum) over (partition by colB, colA, (seqnum_b - seqnum_ab) ) as min_rownum_group,
max(rownum) over (partition by colB, colA, (seqnum_b - seqnum_ab) ) as max_rownum_group
from (select t.*,
row_number() over (partition by colB order by rownum) as seqnum_b,
row_number() over (partition by colB, colA order by rownum) as seqnum_ab,
max(rownum) over (partition by colB order by rownum) as max_rownum
from t
) t
) t
where rownum = min_rownum_group and -- first row in the group defined by adjacent colA, colB
max_rownum_group = max_rownum -- last group for each colB;
这使用不同的行号来标识每个组。它计算数据中组和整体的最大行数。这些与最后一组相同。