2011-03-17 42 views
0

我有一個挑戰,我無法通過任何常規方法找到答案。我想在單個查詢中儘可能地做到這一點,因爲我唯一的另一種選擇是編寫腳本函數並使用無數的子查詢循環它。在SQL中配對項目並減去結果

好了,我有一個MySQL服務器上的一個記錄表,它具有以下欄目: 鍵,用戶名,日期時間和位置 位置可以是「開始」,「登錄」和「結束」。

我想找出每個登錄事件的「開始」,「登錄」和「結束」之間的區別。 任何人都有我可以使用的SQL查詢的想法?我認爲這與查詢中的查詢有關,但我只能找到JOIN?

我假設我會先選擇「開始」事件,然後對於每個「開始」事件,它應該查找「用戶ID」的下一個第一次登錄事件(在「開始」之後但小於下一個「開始」的時間爲相同的「用戶ID」)然後DATE_SUB()找出差異。在未來的「開始」事件發生後發生的「登錄」或「結束」事件過濾將是非常重要的,以防未發生。

如果有人能救我在Excel中這樣做,我將非常感激,因爲那樣我就可以避免在數千個vlookup中感覺太髒。我正考慮在PHP或Perl中執行此操作,並創建一個包含LIMIT 1 SQL語句的循環,但與單個像樣的SQL SELECT語句相比,這可能會創建數千個SQL查詢。

+1

你能告訴我們一個包含5個條目的示例表,以及你正在尋找的結果看起來像給出這5個條目嗎? – Matt 2011-03-17 09:40:14

+1

爲什麼不在同一行更新三個日期?如果你確實知道每個用戶都有開始時間,登錄時間和結束時間,也許你最好用像tbl(key,uid,start,login,end)這樣的表? – Jai 2011-03-17 09:58:48

回答

0

如果您只有開始和結束日期,以下是基本方法。我不太瞭解「登錄」位置如何適應,因此您需要更清楚地解釋您想要的輸出,或者將查詢擺到滿意的位置。此外,查詢是在SQL服務器,因爲我沒有安裝MySQL - 對不起!

CREATE TABLE LogTable 
(
    id int IDENTITY, 
    userId nvarchar(20), 
    logDate datetime, 
    position nvarchar(5)  
) 
GO 

INSERT INTO LogTable (userId, logDate, position) VALUES ('User1', '2001-01-01', 'start') 
INSERT INTO LogTable (userId, logDate, position) VALUES ('User1', '2001-01-02', 'end') 
INSERT INTO LogTable (userId, logDate, position) VALUES ('User1', '2001-01-05', 'start') 
INSERT INTO LogTable (userId, logDate, position) VALUES ('User1', '2001-01-08', 'end') 
INSERT INTO LogTable (userId, logDate, position) VALUES ('User2', '2001-01-01', 'start') 
INSERT INTO LogTable (userId, logDate, position) VALUES ('User2', '2001-01-03', 'end') 
INSERT INTO LogTable (userId, logDate, position) VALUES ('User2', '2001-01-06', 'start') 
INSERT INTO LogTable (userId, logDate, position) VALUES ('User2', '2001-01-07', 'end') 
GO 

SELECT log1.userId, log1.logDate AS [start], log2.logDate AS [end], 
     DATEDIFF(d, log1.logDate, log2.logDate) AS [Diff. in Days] 
FROM LogTable log1 JOIN 
     LogTable log2 ON log1.userId = log2.userId 
WHERE log1.position = 'start' 
AND  log2.position = 'end' 
AND  log2.logDate > log1.logDate 
AND  NOT EXISTS (
    SELECT * 
    FROM LogTable logDateCheck 
    WHERE logDateCheck.userId = log1.userId 
    AND  logDateCheck.logDate >= log1.logDate 
    AND  logDateCheck.logDate <= log2.logDate 
    AND  logDateCheck.id NOT IN (log1.id, log2.id)) 
GO 

輸出是:

Output from query

1

我不知道有關MySQL。 MS SQL Server中我想嘗試類似如下:

SELECT Key, UserID, DateTime, Position, 
    (DateTime - (SELECT MAX(DateTime) FROM <table> t1 
       WHERE t1.UserID=UserID AND t1.DateTime < DateTime)) AS DiffToLastEvent 
FROM <table> 

我還沒有真正嘗試過這一點,但是這就是我想要下手。這應該從表<table>中選擇所有列,並且附加字段包含當前項目與當前項目之前爲用戶創建的最新項目的時差。

+0

如果同一個用戶可以多次登錄,我假設這種情況(問題不明確),這種方法將不起作用。 – 2011-03-17 10:05:55

+1

當然是的。它計算當前事件和上次事件之間的時間,不管事件是什麼。如果允許同一用戶的多次登錄,您可以在某個時間點獲得當前登錄和上次登錄的時間差。我沒有聲稱計算「登錄」時間。 – 2011-03-17 12:50:23

+1

道歉 - 你說得很對。顯然,我頭腦中的SQL解析器需要一些細化......;) – 2011-03-17 13:55:21