SQL: Select Row with Last New Sequentially Distinc

2019-08-27 17:28发布

问题:

EDIT: Please see the updated question here: SQL: Select Most Recent Sequentially Distinct Value w/ Grouping

I am having trouble writing a query that would select the last "new" sequentially distinct value. Since this is a bit ambiguous, here is an example to explain (assume row number is indicative of sequence; in my issue the rows are ordered by date):

|--------|-------|
| RowNum | Col A |
|--------|-------|
| 1      | A     |
| 2      | B     |
| 3      | C     |
| 4      | B     |
| 5      | A     |
| 6      | B     |

Would select:

| 6      | B     |

Although B also appears in rows 2 and 4, the fact that row 5 contains A means that the B in row 6 is sequentially distinct. But if table looked like this:

|--------|-------|
| RowNum | Col A |
|--------|-------|
| 1      | A     |
| 2      | B     |
| 3      | C     |
| 4      | B     |
| 5      | A     |
| 6      | A     | <--

Then we would want to select:

| 5      | A     |

I think that this would be an easier problem if I wasn't concerned with values being distinct but not sequential. I'm not really sure how to even consider sequence when making a query.

I have attempted to solve this by calculating the min/max row numbers where each value of Col A appears. That calculation (using the second sample table) would produce a result like this:

|--------|--------|--------|
| ColA   | MinRow | MaxRow |
|--------|--------|--------|
| A      | 1      | 6      |
| B      | 2      | 4      |
| C      | 3      | 3      | 

However, this is where I get stuck, because although I can properly pick out A as the value to use, I don't know how to use the other rows in this table to recognize that we want A in row 5 (since it is interrupted by B at 4), not A in row 1...

Any help with this problem, if it is at all possible to do in SQL, would be greatly appreciated. I am running SQL 2008 SP4.

回答1:

You can do it by finding the previous RowNum of the row you want as result and then get the next Rownum:

select top 1 *
from tablename
where 
  RowNum > coalesce((
    select max(RowNum) from tablename where colA <> (
      select top 1 colA from tablename order by RowNum desc
    )
  ), 0) 
order by RowNum

See the demo.