2011-07-28 187 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)