下面的查询有效,但我想知道是否有更好的方法。
有一个子查询使用两个子查询。这两个子查询是相同的,但返回两个不同的字段。有没有办法只使用一个返回两个字段的子查询?
我检查了类似的问题(this,this和this),但我不认为它们适用于这种情况。
以下是查询:
SELECT *,
time(strftime('%s', EndTime) - strftime('%s', StartTime), 'unixepoch') AS Duration
FROM (
SELECT (
SELECT Time
FROM Log AS LogStart
WHERE LogStart.User = Log.User AND
LogStart.Time <= Log.Time AND
LogStart.[Action] != 'done'
ORDER BY LogStart.Time DESC
LIMIT 1
)
AS StartTime,
Time AS EndTime,
User,
(
SELECT [Action]
FROM Log AS LogStart
WHERE LogStart.User = Log.User AND
LogStart.Time <= Log.Time AND
LogStart.[Action] != 'done'
ORDER BY LogStart.Time DESC
LIMIT 1
)
AS [Action]
FROM Log
WHERE [Action] = 'done'
)
ORDER BY duration DESC;
以下是一些测试数据:
CREATE TABLE Log (
Time DATETIME,
User CHAR,
[Action] CHAR
);
insert into Log values('2017-01-01 10:00:00', 'Joe', 'Play');
insert into Log values('2017-01-01 10:01:00', 'Joe', 'done');
insert into Log values('2017-01-01 10:02:00', 'Joe', 'Sing');
insert into Log values('2017-01-01 10:03:00', 'Joe', 'done');
insert into Log values('2017-01-01 10:04:00', 'Ann', 'Play');
insert into Log values('2017-01-01 10:04:30', 'Bob', 'Action without corresponding "done" which must be ignored');
insert into Log values('2017-01-01 10:05:00', 'Joe', 'Play');
insert into Log values('2017-01-01 10:06:00', 'Ann', 'done');
insert into Log values('2017-01-01 10:07:00', 'Joe', 'done');
insert into Log values('2017-01-01 10:08:00', 'Ann', 'Play');
insert into Log values('2017-01-01 10:09:00', 'Ann', 'done');
答案 0 :(得分:1)
使用自联接...我没有SQLLite,所以语法可能在这里,但你应该明白...
Select e.*, time(strftime('%s', e.[Time]) -
strftime('%s', s.[Time]), 'unixepoch') AS Duration
From log e join log s -- s is for the startevent; e for end event
on s.[User] = e.[User]
and s.[Action] != 'done'
and e.[Action] = 'done'
and s.[Time] =
(Select Max([time] from log
where [User] = e.[User]
and [time] <= e.[Time]
and [Action] != 'done')
答案 1 :(得分:1)
我做到了:你在寻找什么? ( MSSQL,但我认为应该在SQLLite中工作,因为没有“非标准”SQL命令;我应该在[] 中写入USER。)
SELECT STARTTIME, MIN(ENDTIME) AS ENDTIME, [USER], ACTION
FROM (
SELECT B.TIME AS STARTTIME, A.TIME AS ENDTIME, A.[USER], B.ACTION
FROM LOG A
INNER JOIN (SELECT * FROM LOG) B ON A.[USER]= B.[USER] AND B.ACTION<>'done' AND B.TIME< A.TIME
WHERE A.Action='done'
) X
GROUP BY X.STARTTIME, [USER], ACTION ;
输出:
STARTTIME ENDTIME USER ACTION
----------------------- ----------------------- ---------- ---------------------
2017-01-01 10:00:00.000 2017-01-01 10:01:00.000 Joe Play
2017-01-01 10:02:00.000 2017-01-01 10:03:00.000 Joe Sing
2017-01-01 10:04:00.000 2017-01-01 10:06:00.000 Ann Play
2017-01-01 10:05:00.000 2017-01-01 10:07:00.000 Joe Play
2017-01-01 10:08:00.000 2017-01-01 10:09:00.000 Ann Play
仅使用您的数据,比较MSSQL中的执行计划 显示您的查询“成本”为87%,而后者成本为13%(他们的总和当然是100%)