需要帮助创建SELECT查询以选择唯一行

时间:2011-07-26 15:57:29

标签: sql select sqlite

我想为 SQLite3 DB 创建一个SQL查询。

在我的表格中,我有以下示例数据

7/1/2011   8:02   LOGIN   JOE
7/1/2011   8:15   LOGIN   CAROL
7/1/2011   8:15   LOGIN   JOE
7/1/2011   8:35   LOGIN   SANDY
7/1/2011   13:15  LOGOFF  SANDY
7/1/2011   16:15  LOGIN   SANDY
7/1/2011   18:12  LOGOFF  CAROL
7/1/2011   21:09  LOGOFF  TED
7/1/2011   21:19  LOGIN   TED
7/1/2011   22:10  LOGOFF  JOE
7/1/2011   23:40  LOGOFF  SANDY
7/2/2011   9:00   LOGIN   JOE
7/3/2011   10:00  LOGIN   JOE
7/3/2011   20:00  LOGOFF  SANDY

基本上我想只获得每个日期的第一个LOGIN条目和同一日期的最后一个LOGOFF条目(如果有的话)

所以我希望查询生成

7/1/2011   8:02   LOGIN   JOE
7/1/2011   8:15   LOGIN   CAROL
7/1/2011   8:35   LOGIN   SANDY
7/1/2011   18:12  LOGOFF  CAROL
7/1/2011   21:09  LOGOFF  TED
7/1/2011   21:19  LOGIN   TED
7/1/2011   22:10  LOGOFF  JOE
7/1/2011   23:40  LOGOFF  SANDY
7/2/2011   9:00   LOGIN   JOE
7/3/2011   10:00  LOGIN   JOE
7/3/2011   20:00  LOGOFF  SANDY

正如您所看到的,我们对用户的第一次登录和最后一次注销感兴趣。

所有字段都是单独的字段,存储为VARCHAR() 日期和时间除外 日期存储为DATE 时间存储为TIME 以下是字段名称及其代表的内容。

tddate - date
tdtime - time
tdtype - LOGIN/LOGOFF
tdusername - username

并非所有登录都有相应的注销,因为一个人可能在没有实际注销的情况下断开网络连接。

以下是我尝试使用的查询

select tddate,
        case tdtype
                   when 'LOGIN' then Min(tdtime)          
                   when 'LOGOFF' then Max(tdtime)        
                   end as tdtype  from TimeData                     
WHERE tdusername LIKE "JOE"

我得到0行数据

3 个答案:

答案 0 :(得分:2)

你所拥有的几乎就像你想要的那样。您只需要添加group by子句:

SELECT
    tddate,
    CASE tdtype
        WHEN 'LOGIN' THEN MIN(tdtime)
        WHEN 'LOGOFF' THEN MAX(tdtime)
        ELSE NULL
    END AS tdtime,
    tdtype,
    tdusername
FROM TimeData
GROUP BY tddate, tdtype, tdusername
ORDER BY tddate, tdtime

答案 1 :(得分:0)

你需要自我加入或结合以及结果分区来完成这项工作:

   SELECT * FROM (
SELECT DateField
        , TimeField
        , ActionField
        , UserField
        , RealDate = Max(CAST(DateField + ' ' + TimeField AS DateTime))
        , RowNum = ROW_NUMBER() OVER (PARTITION BY UserField, ActionField ORDER BY Cast(DateField + ' ' + TimeField AS DateTime) DESC)
FROM   theTable
WHERE  ActionField='LOGOFF'
GROUP BY Datefield, TimeField, ActionField, UserField
UNION
SELECT DateField
        , TimeField
        , ActionField
        , UserField
        , RealDate = Max(Cast(DateField + ' ' + TimeField AS DateTime))
        , RowNum = ROW_NUMBER() OVER (PARTITION BY UserField, ActionField ORDER BY Cast(DateField + ' ' + TimeField AS DateTime) DESC)
FROM   theTable
WHERE  ActionField='LOGIN'
GROUP BY Datefield, TimeField, ActionField, UserField) AS Result
WHERE Result.RowNum = 1
ORDER BY UserField, RealDate

编辑:没关系 - 我没有意识到这是SQLite。这里没有row_number函数。你可能需要临时表......

答案 2 :(得分:0)

select tddate, max(tdtime) time, tdtype, tdusername 
from table 
where tdtype = 'LOGIN' 
group by tddate, tdtype, tdusername

union

select tddate, min(tdtime) time, tdtype, tdusername 
from table 
where tdtype = 'LOGOUT' 
group by tddate, tdtype, tdusername