[英]SQL Server : select all rows where Column does not contain any value from dynamic table of values
[英]SQL Server: Select rows where value in column changes from list of values to another list of values
假设我在sql server数据库中有此表,按递增hist_pp排序:
hist_id hist_yr hist_pp hist_empl_id hist_empl_sect_id
90619 2017 5 00018509 61
92295 2017 6 00018509 61
93991 2017 7 00018509 61
95659 2017 8 00018509 99
103993 2017 9 00018509 99
120779 2017 10 00018509 99
我想找到hist_empl_sect_id从一组数字中的任何值(例如(60、61、62、63))更改为另一组数字中的任何值(例如(98、99、100等)的行。 它必须是每年,因此对于2017年的值。hist_pp将在一年中不断增加。 hist_id也是一个id自动编号列。
它应该为这名员工返回
95659 2017 8 00018509 99
我已经尝试了一些我在其他帖子中看到的示例,并与CTE等一起尝试了,但我似乎无法使其正常工作。
这是我尝试但未成功执行的操作的一个示例,当应该只有一个时,会为一个雇员得到多个行:
select a.hist_id, a.hist_yr, format(cast(a.hist_pp as integer), '0#') as hist_pp, a.hist_empl_id, a.hist_empl_sect_id
from temshist a
where a.hist_empl_sect_id <>
(SELECT top 1 b.hist_empl_sect_id
FROM temshist as b
where a.hist_empl_id = b.hist_empl_id
and a.hist_yr = b.hist_yr
and a.hist_pp > b.hist_pp
Order by b.hist_pp desc
)
order by hist_empl_id
我怀疑Lag()在这里很合适。
例
;with cte as (
Select *
,PrevValue= Lag(hist_empl_sect_id,1,hist_empl_sect_id) over (Partition by hist_empl_id Order By hist_pp)
From @YourTable
)
Select *
From cte Where PrevValue/98<>hist_empl_sect_id/98
编辑-VamsiPrabhala指出
您也可以按年份划分
,PrevValue= Lag(hist_empl_sect_id,1,hist_empl_sect_id) over (Partition by hist_yr,hist_empl_id Order By hist_pp)
这是另一种选择,我使用CTE对其进行了模拟,以模拟您的数据,然后再重新加入自身。
with emp_hist as
(
select 90619 as hist_id, 2017 as hist_yr, 5 as hist_pp, '00018509' as hist_empl_id, 61 as hist_empl_sect_id from dual
union all
select 92295 as hist_id, 2017 as hist_yr, 6 as hist_pp, '00018509' as hist_empl_id, 61 as hist_empl_sect_id from dual
union all
select 93991 as hist_id, 2017 as hist_yr, 7 as hist_pp, '00018509' as hist_empl_id, 61 as hist_empl_sect_id from dual
union all
select 95659 as hist_id, 2017 as hist_yr, 8 as hist_pp, '00018509' as hist_empl_id, 99 as hist_empl_sect_id from dual
union all
select 103993 as hist_id, 2017 as hist_yr, 9 as hist_pp, '00018509' as hist_empl_id, 99 as hist_empl_sect_id from dual
union all
select 120779 as hist_id, 2017 as hist_yr, 10 as hist_pp, '00018509' as hist_empl_id, 99 as hist_empl_sect_id from dual
)
select eh2.*
from emp_hist eh1
join emp_hist eh2
on eh1.hist_empl_id = eh2.hist_empl_id
and eh1.hist_pp = (eh2.hist_pp - 1)
and eh1.hist_yr = eh2.hist_yr
where eh2.hist_empl_sect_id in (98, 99, 100)
and eh1.hist_empl_sect_id in (60, 61, 62, 63)
;
您可以使用case语句(确定组成员身份)和滞后窗口函数(比较两个连续的行),按员工和年份划分并按hist_pp排序
这假设(1)员工ID可以跨越多年(2)每个员工ID,年份组合的Hist_pp都是唯一的(3)如果员工ID,年份组合中的hist_empl_sect_id只有一个唯一值,则(hist_empl_sect_id不会更改该员工在该年份),结果集不应包含该员工ID,年份组合的任何行。
Hist_pp可以有空白。
select hist_id, hist_yr, hist_pp, hist_empl_id, hist_empl_sect_id
from
(
select a.hist_id, a.hist_yr,
format(cast(a.hist_pp as integer), '0#') as hist_pp,
a.hist_empl_id,
-- hist_empl_sect_id of current row
a.hist_empl_sect_id,
-- hist_empl_sect_id of preceding row, when ordered by hist_pp for each employee year combination
lag(a.hist_empl_sect_id, 1)
OVER (
PARTITION BY a.hist_empl_id,a.hist_yr
ORDER BY format(cast(a.hist_pp as integer), '0#')
) as prev_hist_empl_sect_id
from temshist a
) as outr
where
-- group membership of hist_empl_sect_id of current row
(case when hist_empl_sect_id IN (98, 99, 100) then 1 else 0 end)
<>
-- group membership of hist_empl_sect_id of preceding row, ordered by hist_pp for each year
(case when prev_hist_empl_sect_id IN (98, 99, 100) then 1 else 0 end)
AND
-- Preceding row does not belong to a different employee or year
prev_hist_empl_sect_id IS NOT NULL
查看您的结果数据,我假设针对每个hist_yr
和hist_empl_id
,您需要其中hist_pp
为min
且hist_empl_sect_id
为max
的记录行,以下是将生成所需输出的查询。
SELECT t3.* from
(SELECT t2.*, min(hist_pp) over(partition BY hist_yr, hist_empl_id) AS hist_pp_minValue
FROM
(SELECT hist_id, hist_yr, hist_pp, hist_empl_id, hist_empl_sect_id, r1, max(r1) over (partition BY hist_yr, hist_empl_id) AS maxRank
FROM
(SELECT hist_id, hist_yr, hist_pp, hist_empl_id, hist_empl_sect_id, dense_rank() over(partition BY hist_yr, hist_empl_id
ORDER BY hist_empl_sect_id) AS r1
FROM table1)t1) t2
WHERE t2.maxRank = t2.r1 )t3
WHERE t3.hist_pp_minValue = t3.hist_pp
我已经对有问题的数据进行了测试,以下是结果。
hist_id | hist_yr | hist_pp | hist_empl_id | hist_empl_sect_id
---------------------------------------------------------
95659 2017 8 18509 99
为了保证安全,我添加了以下更多示例数据。
insert into table1 values(90619 ,2018,5 ,00018508,62);
insert into table1 values(92295 ,2018,6 ,00018508,62);
insert into table1 values(93991 ,2018,7 ,00018508,62);
insert into table1 values(95659 ,2018,8 ,00018508,91);
insert into table1 values(103993 ,2018,9 ,00018508,91);
insert into table1 values(120779 ,2018,10 ,00018508,91);
以下是生成的结果。
hist_id | hist_yr | hist_pp | hist_empl_id | hist_empl_sect_id
---------------------------------------------------------
95659 2017 8 18509 99
95659 2018 8 18508 91
您可以在这里查看演示
希望这会有所帮助。
我认为您将需要使用CTE解决此问题。 这类似于John Cappelletti所做的事情,但不需要SQL 2012或更高版本。
declare @temshist table
(
hist_id int,
hist_yr int,
hist_pp int,
hist_empl_id varchar(max),
hist_empl_sect_id int
)
insert into @temshist ( hist_id, hist_yr, hist_pp, hist_empl_id, hist_empl_sect_id )
values
( 90619, 2017, 5, '00018509', 61 ),
( 92295, 2017, 6, '00018509', 61 ),
( 93991, 2017, 7, '00018509', 61 ),
( 95659, 2017, 8, '00018509', 99 ),
( 103993, 2017, 9, '00018509', 99 ),
( 120779, 2017, 10, '00018509', 99 )
;with empl_cte as
(
select
row_number() over (partition by hist_empl_id, hist_yr order by hist_pp) as [rn],
hist_id,
hist_yr,
hist_pp,
hist_empl_id,
hist_empl_sect_id
from @temshist
)
select
nxt.hist_id,
nxt.hist_yr,
nxt.hist_pp,
nxt.hist_empl_id,
nxt.hist_empl_sect_id
from empl_cte prv
left join empl_cte nxt on
prv.hist_empl_id = nxt.hist_empl_id and
prv.rn = nxt.rn - 1
where prv.hist_empl_sect_id in (60, 61, 62, 63/*, ...*/) and nxt.hist_empl_sect_id in (98, 99, 100/*, ...*/)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.