2011-07-28 220 views
0

需要查詢幫助。我在那裏的數據是這樣表示需要查詢幫助

userid TransactionTime   FunctionKey 
1018  2011-07-27 09:14:38.000 0 
1018  2011-07-27 09:17:11.000 99 
1018  2011-07-27 09:38:22.000 0 
1018  2011-07-27 10:34:50.000 99 

我需要一個查詢將返回這樣的數據集的表:

userid Intime     Outtime 
1018 2011-07-27 09:14:38.000 2011-07-27 09:17:11.000 
1018 2011-07-27 09:38:22.000 2011-07-27 10:34:50.000 

請幫助..

+0

當Funtionkey爲0時,它的銀泰,當它是99,然後是它的運行時間 –

+0

你是否需要處理'假'數據? (同時登錄和註銷,登錄後登錄,註銷後註銷等等) – MatBailie

+0

爲什麼在這個問題上downvotes!?!? – MatBailie

回答

4
declare @T table (userid int, TransactionTime datetime, FunctionKey int) 
insert into @T values 
(1018,  '2011-07-27 09:14:38.000', 0), 
(1018,  '2011-07-27 09:17:11.000', 99), 
(1018,  '2011-07-27 09:38:22.000', 0), 
(1018,  '2011-07-27 10:34:50.000', 99), 
(1019,  '2011-07-27 09:14:38.000', 0), 
(1019,  '2011-07-27 09:17:11.000', 0), 
(1019,  '2011-07-27 09:38:22.000', 99), 
(1020,  '2011-07-27 09:14:38.000', 0), 
(1020,  '2011-07-27 09:17:11.000', 99), 
(1020,  '2011-07-27 09:38:22.000', 99) 

;with cte as 
( 
    select userid, 
     TransactionTime, 
     FunctionKey, 
     row_number() over(partition by userid order by TransactionTime) as rn 
    from @T 
) 
select C1.userid, 
     C1.TransactionTime as InTime, 
     C2.TransactionTime as OutTime 
from cte as C1 
    left outer join cte as C2 
    on C1.userid = C2.userid and 
     C1.rn + 1 = C2.rn 
where C1.FunctionKey = 0 

結果:

userid  InTime     OutTime 
----------- ----------------------- ----------------------- 
1018  2011-07-27 09:14:38.000 2011-07-27 09:17:11.000 
1018  2011-07-27 09:38:22.000 2011-07-27 10:34:50.000 
1019  2011-07-27 09:14:38.000 2011-07-27 09:17:11.000 
1019  2011-07-27 09:17:11.000 2011-07-27 09:38:22.000 
1020  2011-07-27 09:14:38.000 2011-07-27 09:17:11.000 
+0

是否假定每個註銷都立即以登錄爲前提,且登錄從不會立即以登錄爲前提。 +1,因爲OP沒有明確說明。 – MatBailie

+0

這將工作得很好Mikael ...但如果兩個連續的行具有相同的FunctionKey值呢? –

+0

@Tanvir - 你想如何處理這種情況? (我的答案是以一種方式處理它,另一種選擇是過濾除* * last *之外的所有「重複」註銷以及除第一個*「重複」登錄外的所有內容。不知道你想要什麼,我們不能給你一個鑄鐵答案。) – MatBailie

0

將表與自身,採取從每一個時間戳:

select 
    t1.userid, 
    t1.TransactionTime as InTime 
    t2.TransactionTime as Outtime 
from mytable t1 
join mytable t2 on t2.userid = t1.userid and t2.FunctionKey = 99 
where t1.FunctionKey = 0; 
+1

這將將記錄1匹配到記錄2和4,並將記錄3也記錄到記錄2和4. – MatBailie

2
WITH 
    ordered AS 
(
    SELECT 
    ROW_NUNBER() OVER (PARTITION BY userid ORDER BY TransactionTime, FunctionKey) item_id, 
    * 
    FROM 
    myTable 
) 
, logins AS 
(
    SELECT * FROM ordered WHERE FunctionKey = 0 
) 
, logouts AS 
(
    SELECT * FROM ordered WHERE FunctionKey = 99 
) 

SELECT 
    COALESCE([logins].userid, [logouts].userid), 
    [logins].TransactionTime, 
    [logouts].TransactionTime 
FROM 
    [logins] 
FULL OUTER JOIN 
    [logouts] 
    ON [logouts].userid  = [logins].userid 
    AND [logouts].item_id  = [logins].item_id + 1 
    AND [logouts].FunctionKey <> [logins].FunctionKey 
ORDER BY 
    COALESCE([logins].TransactionTime, [logouts].TransactionTime) 

可替代地,這一個與通過取最後註銷通過取第一登錄的登錄序列,和logogut的序列涉及。

WITH 
    ordered AS 
(
    SELECT 
    ROW_NUNBER() OVER (PARTITION BY userid ORDER BY TransactionTime, FunctionKey) 
    - 
    ROW_NUMBER() OVER (PARTITION BY userid, FunctionKey ORDER BY TransactionTime) 
    AS group_id, 
    * 
    FROM 
    myTable 
) 
, 
    filtered AS 
(
    SELECT 
    userid, 
    FunctionKey, 
    CASE WHEN FunctionKey = 0 THEN MIN(TransactionTime) ELSE MAX(TransactionTime) END AS TransactionTime 
    FROM 
    ordered 
    GROUP BY 
    userid, 
    FunctionKey, 
    group_id 
) 
, 
    sequenced AS 
(
    SELECT 
    ROW_NUMBER() OVER (PARTITION BY userid ORDER BY TransactionTime, FunctionKey) AS item_id, 
    * 
    FROM 
    filtered 
) 
, logins AS 
(
    SELECT * FROM sequenced WHERE FunctionKey = 0 
) 
, logouts AS 
(
    SELECT * FROM sequenced WHERE FunctionKey = 99 
) 

SELECT 
    COALESCE([logins].userid, [logouts].userid), 
    [logins].TransactionTime, 
    [logouts].TransactionTime 
FROM 
    [logins] 
FULL OUTER JOIN 
    [logouts] 
    ON [logouts].userid  = [logins].userid 
    AND [logouts].item_id  = [logins].item_id + 1 
    AND [logouts].FunctionKey <> [logins].FunctionKey 
ORDER BY 
    COALESCE([logins].TransactionTime, [logouts].TransactionTime)