我有一张桌子
Val | Number
08 | 1
09 | 1
10 | 1
11 | 3
12 | 0
13 | 1
14 | 1
15 | 1
我需要返回 Number = 1 的最后一个值(无论可能有多少),直到 Number 更改,但不需要 Number = 1 的第一个实例。基本上我需要选择返回,直到 Number 更改为 0(15、14、 13)
在 MSSQL 中是否有适当的方法来执行此操作?
我有一张桌子
Val | Number
08 | 1
09 | 1
10 | 1
11 | 3
12 | 0
13 | 1
14 | 1
15 | 1
我需要返回 Number = 1 的最后一个值(无论可能有多少),直到 Number 更改,但不需要 Number = 1 的第一个实例。基本上我需要选择返回,直到 Number 更改为 0(15、14、 13)
在 MSSQL 中是否有适当的方法来执行此操作?
基于以下:
我需要返回 Number = 1 的最后一个值
基本上我需要选择回来,直到 Number 更改为 0 (15, 14, 13)
试试(小提琴演示):
select val, number
from T
where val > (select max(val)
from T
where number<>1)
编辑:解决所有可能的组合(小提琴演示 2)
;with cte1 as
(
select 1 id, max(val) maxOne
from T
where number=1
),
cte2 as
(
select 1 id, isnull(max(val),0) maxOther
from T
where val < (select maxOne from cte1) and number<>1
)
select val, number
from T cross join
(select maxOne, maxOther
from cte1 join cte2 on cte1.id = cte2.id
) X
where val>maxOther and val<=maxOne
我认为您可以使用窗口函数,如下所示:
with cte as (
-- generate two row_number to enumerate distinct groups
select
Val, Number,
row_number() over(partition by Number order by Val) as rn1,
row_number() over(order by Val) as rn2
from Table1
), cte2 as (
-- get groups with Number = 1 and last group
select
Val, Number,
rn2 - rn1 as rn1, max(rn2 - rn1) over() as rn2
from cte
where Number = 1
)
select Val, Number
from cte2
where rn1 = rn2
演示:http ://sqlfiddle.com/#!3/e7d54/23
create table T(val int identity(8,1), number int)
insert into T values
(1),(1),(1),(3),(0),(1),(1),(1),(0),(2)
; WITH last_1 AS (
SELECT Max(val) As val
FROM t
WHERE number = 1
)
, last_non_1 AS (
SELECT Coalesce(Max(val), -937) As val
FROM t
WHERE EXISTS (
SELECT val
FROM last_1
WHERE last_1.val > t.val
)
AND number <> 1
)
SELECT t.val
, t.number
FROM t
CROSS
JOIN last_1
CROSS
JOIN last_non_1
WHERE t.val <= last_1.val
AND t.val > last_non_1.val
我知道这有点冗长,但我故意保持这种方式来说明方法。
val
地方number=1
。val
小于步骤 1 中找到的数字的所有值,找到最大val
的number<>1
select val, count (number) from
yourtable
group by val
having count(number) > 1
have 子句是这里的关键,它为您提供了所有值超过一个 1 的 val。
这是获取行直到某些值更改的常用方法。对于您的特定情况,请在适当的位置使用desc。
创建样本表
select * into #tmp from
(select 1 as id, 'Alpha' as value union all
select 2 as id, 'Alpha' as value union all
select 3 as id, 'Alpha' as value union all
select 4 as id, 'Beta' as value union all
select 5 as id, 'Alpha' as value union all
select 6 as id, 'Gamma' as value union all
select 7 as id, 'Alpha' as value) t
拉顶部行,直到值更改:
with cte as (select * from #tmp t)
select * from
(select cte.*, ROW_NUMBER() over (order by id) rn from cte) OriginTable
inner join
(
select cte.*, ROW_NUMBER() over (order by id) rn from cte
where cte.value = (select top 1 cte.value from cte order by cte.id)
) OnlyFirstValueRecords
on OriginTable.rn = OnlyFirstValueRecords.rn and OriginTable.id = OnlyFirstValueRecords.id
在左侧,我们放了一张原始桌子。在右侧,我们只放置其值等于第一行中的值的行。
两个表中的记录将相同,直到目标值更改。在第 3 行之后,行号将因为偏移而获得不同的关联 ID,并且永远不会与原始表连接:
LEFT RIGHT
ID Value RN ID Value RN
1 Alpha 1 | 1 Alpha 1
2 Alpha 2 | 2 Alpha 2
3 Alpha 3 | 3 Alpha 3
----------------------- result set ends here
4 Beta 4 | 5 Alpha 4
5 Alpha 5 | 7 Alpha 5
6 Gamma 6 |
7 Alpha 7 |
ID 必须是唯一的。在两个 ROW_NUMBER() 函数中,此 ID 的排序必须相同。