2016-07-29 33 views
0

不明道名的道歉。SQL Server - 多個事務ID - 如果包含 - 只選擇最近

我正在嘗試在SQL中創建時間驗證報告,但遇到了問題。

我面臨的問題是,有時員工提交時間後,支持人員會進行更改,區分這些問題的唯一方法是通過交易ID進行區分。例如,如果John Doe提交了他的時間卡,他在表中的交易ID將是1234,但是如果對該條目進行了更改,則表中的交易ID將是1234-00,然後是1234-01,然後是1234-02等等爲每個變化。我想要做的是改變我的SQL查詢,以便如果事務ID包含 - 它只選擇最新的條目。

見下面的代碼示例:

SELECT 
    jb_id AS JobID, 
    MAX(jb_nme) AS JobName, 
    MAX(emplye_nme_frst) + ' ' + MAX(emplye_nme_lst) AS FullName, 
    jchstry_dte_effctve AS EffectiveDate, 
    jchstry_hrs, 
    pytype_id PayType, 
    jbcstctgry_id, 
    jbcstctgry_dscrptn, 
    jchstry_srce_trnsctn_id 
FROM jb 
JOIN jbbllngitm 
    ON jbbllngitm.jb_rn = jb.jb_rn 
JOIN jbcstcde 
    ON jbcstcde.jb_rn = jb.jb_rn 
JOIN jchstry 
    ON jbcstcde.jbcstcde_rn = jchstry.jbcstcde_rn 
JOIN pytype 
    ON pytype.pytype_rn = jchstry.pytype_rn 
JOIN jbcstctgry 
    ON jbcstctgry.jbcstctgry_rn = jchstry.jbcstctgry_rn 
JOIN emplye 
    ON jchstry_rfrnce_rn = emplye.emplye_rn 
WHERE jb_id = '1234' 
AND jchstry_dte_effctve BETWEEN 'XXXX-04-01' AND 'XXXX-04-04' 
GROUP BY jbcstcde_nme, 
     jb.jb_rn, 
     jchstry.jchstry_dte_effctve, 
     jb.jb_id, 
     pytype.pytype_id, 
     jbcstctgry.jbcstctgry_id, 
     jbcstctgry.jbcstctgry_dscrptn, 
     jchstry.jchstry_hrs, 
     jchstry.jchstry_srce_trnsctn_id 

樣本數據集

JobID JobName FullName EffectiveDate Hours PayType Source Transaction ID 
1234 XXXX John Doe 4/1/XXXX  0.25 Straight Time  5678 
1234 XXXX John Doe 4/1/XXXX  8  Straight Time  5678-01 
1234 XXXX John Doe 4/4/XXXX  8  Straight Time  4567 

例如,在上表中,因爲有兩個交易編號爲5678我只是想選擇包含交易ID -01。如果結果具有事務ID 5678-01,5678-02和5678-03,我只希望查詢返回5678-03所在行。

請讓我知道,如果有什麼不清楚。這比我預料的更難解釋。

+0

把'01'放在一個新列中,並通過事務ID查詢該列和組的最大值? – dfundako

+0

但有些條目根本沒有任何-01,-02的值。 4567交易ID是正確的,沒有任何更改。 –

+0

是否有日期時間戳記列記錄每次更改後的時間戳記?以及您正在使用哪個版本的SQL-Server? – objectNotFound

回答

0

你們太聰明瞭,我無法回答你的答案。我今天弄明白了。這是我最終的結果。再次感謝所有人的幫助。

With TimeVerifcation as (
select 
jb_id as JobID, 
max(jb_nme) as JobName, 
emplye_id as EmployeeID, 
max(emplye_nme_frst) + ' ' + max(emplye_nme_lst) as FullName, 
jbbllngitm_dscrptn as JobBillingItem, 
jchstry_dte_effctve as EffectiveDate, 
jchstry_hrs as Hours, 
max(pytype_id) PayType, 
jbcstctgry_id as CostCategoryID, 
jbcstctgry_dscrptn as CostCategoryDescription, 
row_number() over (partition by jbbllngitm_dscrptn,jchstry_dte_effctve,emplye_id,pytype_id order by jchstry_pstd_dte + ' ' + jchstry_pstd_tme desc) as RN 
from jb 
join jbcstcde on jbcstcde.jb_rn = jb.jb_rn 
join jchstry on jbcstcde.jbcstcde_rn = jchstry.jbcstcde_rn 
join pytype on pytype.pytype_rn = jchstry.pytype_rn 
join jbcstctgry on jbcstctgry.jbcstctgry_rn = jchstry.jbcstctgry_rn 
join emplye on jchstry_rfrnce_rn = emplye.emplye_rn 
join jbbllngitm on jbbllngitm.jbbllngitm_rn = jchstry.jbbllngitm_rn 
where jb_id = '72681-00' 
and emplye_nme_lst = 'Cortez' 
and jchstry_dte_effctve between '2016-04-01' and '2016-04-04' 
group by jchstry.jchstry_dte_effctve,jb.jb_id,jbcstctgry.jbcstctgry_id,jbcstctgry.jbcstctgry_dscrptn,jchstry.jchstry_hrs,jbbllngitm.jbbllngitm_dscrptn,emplye.emplye_id,pytype.pytype_id,jchstry.jchstry_pstd_dte,jchstry.jchstry_pstd_tme 
) 
Select * 
from TimeVerifcation 
where RN=1 
order by EffectiveDate 
1

如果沒有唯一的ID列,並且沒有最後一個條目的時間戳,則可以內部連接到它自己。以下是您提供的結果。內部連接是最大的transactionID。這裏的關鍵是在連接中包含足夠多的列以保持唯一性,同時忽略將被編輯的列。不優雅但也不是沒有時間戳或唯一的ID列 DROP TABLE #TEMP

SELECT 
1234 as JobID,'XXXX' as JobName,'John Doe' as FullName,'4/1/2016' as EffectiveDate,0.25 as Hours,'Straight' as PayType,'Time' as Source,'5678' as TransactionID 
INTO #temp 
UNION ALL 
SELECT 
1234,'XXXX','John Doe','4/1/2016',8,'Straight','Time','5678-01' 
UNION ALL 
SELECT 
1234,'XXXX','John Doe','4/4/2016',8,'Straight','Time','4567' 

SELECT * FROM #temp 

SELECT 
    t.JobID, t.JobName, t.FullName, t.EffectiveDate, t.Hours, t.PayType, t.Source, t.TransactionID 
FROM 
    #temp t 
INNER JOIN 
    (SELECT JobID, JobName, FullName, EffectiveDate, PayType, Source, MAX(TransactionID) TransactionID 
    FROM #temp 
    GROUP BY JobID, JobName, FullName, EffectiveDate, PayType, Source) t2 on 
    t2.JobID = t.JobID and 
    t2.JobName = t.JobName and 
    t2.FullName = t.FullName and 
    t2.EffectiveDate = t.EffectiveDate and 
    t2.PayType = t.PayType and 
    t2.Source = t.Source and 
    t2.TransactionID = t.TransactionID 
+0

有一個jchstry_id列以及jchstry_pstd_tme –

1

我測試SSMS中按照您的要求。它工作得很好。 PS:我使用臨時表#test作爲具有給定結構和數據的表。請適當地進行修改。 :)

-- Create table structure 
    create table #test(
     JobID int, 
     JobName varchar(10), 
     FullName varchar(50), 
     EffectiveDate date, 
     Hours money, 
     PayType varchar(10), 
     Source varchar(10), 
     TransactionID varchar(10) 
    ) 

--Insert Data into the temp table  
     insert #test 
     select 1234, 'XXXX', 'John Doe', '4/1/1990',  0.25, 'Straight', 'Time',  '5678' 
     union all 
     select 1234, 'XXXX', 'John Doe', '4/1/1990',  8, 'Straight', 'Time',  '5678-01' 
     union all 
     select 1234, 'XXXX', 'John Doe', '4/4/1990',  8, 'Straight', 'Time',  '4567' 
     union all 
     select 1234, 'XXXX', 'John Doe', '4/1/1990',  9, 'Straight', 'Time',  '5678-02' 
     union all 
     select 1234, 'XXXX', 'John Doe', '4/6/1990',  123, 'Straight', 'Time',  '5678-03' 
     union all 
     select 1234, 'XXXX', 'John Doe', '4/12/1990',  23, 'Straight', 'Time',  '5678-04' 


     insert #test 
     select 2345, 'XXXX', 'John Doe', '4/12/1990',  23, 'Straight', 'Time',  '2342' 
     union all 
     select 2345, 'XXXX', 'John Doe', '4/12/1990',  23, 'Straight', 'Time',  '2342-01' 

--Below is the solution for this question. 

     select jobid,jobname,fullname,effectivedate,hours,paytype,source,transactionid 
       from 
       (
        select *,max(a.orderbyid_in)over(partition by a.partitionid) as orderbyid_out 
        from 
        (
         select *, 
          (case when charindex('-',TransactionID) <> 0 then left(TransactionID,charindex('-',TransactionID)-1) 
            else TransactionID 
          end) as partitionid, 
          (case when charindex('-',TransactionID) <> 0 then right(TransactionID,charindex('-',reverse(TransactionID))-1) 
            else '00' 
          end) as orderbyid_in 
         from #test 

        ) as a 


       ) as b 
       where (transactionid = partitionid and orderbyid_out = '00') 
         or 
         (transactionid = partitionid +'-'+orderbyid_out) 
1

下面是我們如何才能解決這個(感謝@舞 - 亨利一些,我修改了測試數據)

create table #test 
    (
     JobID int, 
     JobName varchar(10), 
     FullName varchar(50), 
     EffectiveDate date, 
     Hours money, 
     PayType varchar(10), 
     Source varchar(10), 
     TransactionID varchar(10), 
     jchstry_id int, 
     jchstry_pstd_tme datetime 
    ) 

    delete #test 

--Insert Data into the temp table  
     insert #test 
     select 1234, 'XXXX', 'John Doe', '4/1/2016',  0.25, 'Straight', 'Time',  '5678' , 1, '4/1/2016 01:00:00' 
     union all 
     select 1234, 'XXXX', 'John Doe', '4/1/2016',  8, 'Straight', 'Time',  '5678-01' , 2, '4/1/2016 02:00:00' 
     union all 
     select 1234, 'XXXX', 'John Doe', '4/4/2016',  8, 'Straight', 'Time',  '4567' , 1 , '4/4/2016 03:00:00' 
     union all 
     select 1234, 'XXXX', 'John Doe', '4/1/2016',  9, 'Straight', 'Time',  '5678-02' , 3 , '4/1/2016 03:00:00' 
     union all 
     select 1234, 'XXXX', 'John Doe', '4/6/2016',  123, 'Straight', 'Time',  '5678-03' , 4, '4/6/2016 04:00:00' 
     union all 
     select 1234, 'XXXX', 'John Doe', '4/12/2016',  23, 'Straight', 'Time',  '5678-04' , 5, '4/12/2016 05:00:00' 
     union all 
     select 2345, 'XXXX', 'Mike Smith', '4/12/2016',  23, 'Straight', 'Time',  '2342' , 1 , '4/12/2016 03:00:00' 
     union all 
     select 2345, 'XXXX', 'Mike Smith', '4/12/2016',  23, 'Straight', 'Time',  '2342-01' , 2 , '4/12/2016 04:00:00' 

查詢:

Select * From 
(

select *, 
Left(TransactionID+'-', CHARINDEX('-',TransactionID+'-')) Lft, 
Rank() Over (Partition by FullName, Left(TransactionID+'-', CHARINDEX('-',TransactionID+'-')) Order By jchstry_id desc , jchstry_pstd_tme desc) as Rnk 
from #test 

) A Where Rnk =1 

邏輯:它按FullName,Transaction_ID(上行破折號)排列行,最舊的記錄排在rank = 1,因爲我們是orderin g by jchstry_id desc,jchstry_pstd_tme desc。之後,我們只選擇那些Rnk = 1的記錄。