2011-07-26 88 views
1

我想爲SQLite3 DB創建一個SQL查詢。需要幫助創建一個SELECT查詢來選擇唯一的行

在我的表,我有以下的樣本數據

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 

基本上我想只得到每個日期的第一次登錄入口和同日的最後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() EXCEPT DATE和TIME 日期存儲爲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行數據

+0

爲什麼tdtime和tddate分離和更重要:爲什麼它是varchar? – Jacob

+0

我如何「轉換」它而不會丟失數據? –

+0

你確定JOE應該用雙引號嗎?另外,如果兩列的標籤都沒有相同的標籤,則清晰度可能會更好(對於兩種情況,後兩者都是「tdtype」)。噢,並且在tddate和tdtype上的Group By會很好... –

回答

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 
+0

爲什麼第一個入口tdtime總是顯示爲NULL?我檢查了數據,看它是否真的是空的,但沒有。 –

+0

我的猜測是你有一個額外的空間字符。它既不等於「LOGIN」也不等於「LOGOFF」,所以它必須是別的東西。 –

+0

當我運行一個簡單的查詢(SELECT tdtime,tddate,tdtype FROM TiMEDATA WHERE tdusername LIKE「JOE」ORDER BY tddate,tdtime ASC);我獲得了所有的數據。 –

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函數。你可能需要臨時表......

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