簡體   English   中英

SQL Server:選擇行,其中列中的值從值列表更改為另一個值列表

[英]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_yrhist_empl_id ,您需要其中hist_ppminhist_empl_sect_idmax的記錄行,以下是將生成所需輸出的查詢。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM