Сопряжение элементов в SQL и вычитание результата - PullRequest
0 голосов
/ 17 марта 2011

У меня есть вызов, на который я не могу найти ответы каким-либо нормальным способом.Я хочу сделать как можно больше за один запрос, потому что моей единственной альтернативой является сценарий этой функции и цикл по каждому циклу с бесчисленными подзапросами.

Хорошо, поэтому у меня есть таблица журналов на сервере MySQL, он имеет следующие столбцы: ключ, идентификатор пользователя, дата и время. Позиция может быть «начало», «логин» и «конец».

Я хочу выяснить разницу между «старт», «логин»и «конец» для каждого события входа в систему.У кого-нибудь есть идея SQL-запроса, который я мог бы использовать?Я думаю, что это как-то связано с запросом внутри запроса, но я могу только найти JOINs?

Я постулирую, что сначала выберу «стартовые» события, а затем для каждого «стартового» события, которое он должен искатьследующее первое событие входа в систему для «UserID» (после времени «start», но меньше, чем время следующего «start» для того же «UserID»), затем DATE_SUB (), чтобы выяснить разницу.Было бы важно отфильтровать события «входа» или «завершения», которые происходят после будущего события «запуска», если этого не произойдет.

Я был бы очень признателен, если бы кто-нибудь смог спасти меня, сделав этов Excel, потому что тогда я могу избежать ощущения себя слишком грязным с тысячами просмотров.Я собираюсь сделать это на PHP или Perl и просто создать цикл с SQL-операторами LIMIT 1, но это может создать тысячи SQL-запросов по сравнению с одним достойным SQL-оператором SELECT.

Ответы [ 2 ]

1 голос
/ 17 марта 2011

Я не уверен насчет 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 голосов
/ 17 марта 2011

Вот основной подход, если у вас есть только даты начала и окончания.Я не совсем понимаю, как вписывается позиция входа в систему, поэтому вам нужно будет более четко объяснить, какой вывод вы хотите получить, или возиться с запросом, чтобы удовлетворить вас.Кроме того, запрос находится на сервере 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

...