Sqlite 哪个记录与group by一起使用?
下面的代码符合我的需要,但我不明白为什么,因此我不知道它是否可靠/正确 我试图计算每个动作的持续时间。每个操作的开始时间由“操作”列中的操作名称标记,结束时间由单词“完成”标记。如果两个操作具有不同的用户,但不具有相同的用户,则两个操作在时间上可能重叠 我想搜索每个Sqlite 哪个记录与group by一起使用?,sqlite,join,Sqlite,Join,下面的代码符合我的需要,但我不明白为什么,因此我不知道它是否可靠/正确 我试图计算每个动作的持续时间。每个操作的开始时间由“操作”列中的操作名称标记,结束时间由单词“完成”标记。如果两个操作具有不同的用户,但不具有相同的用户,则两个操作在时间上可能重叠 我想搜索每个Action='Done'以及具有相同用户的记录,以及该记录之前的最长时间。我试着在不同的位置使用Max()来找到最高的Start.Time,这样Start.Time
Action='Done'
以及具有相同用户的记录,以及该记录之前的最长时间。我试着在不同的位置使用Max()
来找到最高的Start.Time
,这样Start.Time
,但它一直不起作用。我尝试在子查询中使用Max(),但是子查询中的Start
和Join
中的Start
不一样。所以我删除了Max()
,得到了我想要的东西
为什么开始和结束记录正确匹配,而不是匹配每个用户的第一个和最后一个记录
它是否总是根据Order by
子句可靠地拾取组的最后一条记录?还是我只是幸运
以下是创建表、插入一些测试数据和执行查询的代码:
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: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');
SELECT Start.*,
[End].*,
strftime('%s', [End].Time) - strftime('%s', Start.Time) AS Duration
FROM Log AS Start
JOIN
Log AS [End] ON Start.User = [End].User AND
Start.Time < [End].Time
WHERE [End].[Action] = 'Done'
GROUP BY [End].Time
ORDER BY Duration DESC,
Start.Time;
创建表日志(
时间日期时间,
用户字符,
[动作]字符
);
在日志值中插入('2017-01-01 10:00:00','Joe','Play');
在日志值中插入('2017-01-01 10:01:00','Joe','Done');
在日志值中插入('2017-01-01 10:02:00','Joe','Sing');
在日志值中插入('2017-01-01 10:03:00','Joe','Done');
插入日志值(“2017-01-01 10:04:00”、“安”、“播放”);
在日志值中插入('2017-01-01 10:05:00','Joe','Play');
在日志值中插入('2017-01-01 10:06:00','Ann','Done');
在日志值中插入('2017-01-01 10:07:00','Joe','Done');
插入日志值(“2017-01-01 10:08:00”、“安”、“播放”);
在日志值中插入('2017-01-01 10:09:00','Ann','Done');
选择开始。*,
[完],
strftime('%s',[End].Time)-strftime('%s',Start.Time)作为持续时间
从日志作为开始
参加
在开始时以[End]的身份登录。用户=[End]。用户和
开始。时间<[End]。时间
其中[End].[Action]='Done'
按[结束]分组。时间
按持续时间顺序描述,
开始。时间;
来自官方:
当聚合函数为
最小值()或最大值()。例如:
SELECT a, b, max(c) FROM tab1 GROUP BY a;
当最小值()或最大值()
聚合函数用于聚合查询中,所有空列
在结果集中,从同样包含
最小值或最大值。因此,在上面的查询中,“b”的值
输出中的列将是输入中“b”列的值
具有最大“c”值的行。如果有两种情况,仍然存在歧义
或多个输入行具有相同的最小值或最大值,或者
查询包含多个min()和/或max()聚合
功能。只有内置的min()和max()函数可以这样工作
因此,如果查询中只有一个MIN
或MAX
调用,那么所有既不是聚合函数也不是分组依据
列的其他选定列将使用出现最小值或最大值的行(或者更准确地说,一行,因为该列不一定是唯一的)
否则,它只会从属于组的任意行返回值
当然,这是特定于SQLite的行为,不是标准SQL的一部分。例如,Microsoft SQL Server提供了以下错误:
列“b”在选择列表中无效,因为它未包含在聚合函数或GROUP BY子句中
为了避免混淆和最大限度地提高可移植性,我建议避免使用此“功能”
编辑:这是您需要的吗
SELECT
User,
Start.Action AS Action,
MAX(Start.Time) AS StartTime,
End.Time AS EndTime,
STRFTIME('%s', End.Time) - STRFTIME('%s', MAX(Start.Time)) AS Duration
FROM Log Start INNER JOIN Log End USING (User)
WHERE Start.Action != 'Done' AND End.Action = 'Done' AND Start.Time <= End.Time
GROUP BY User, Start.Action, End.Time
选择
用户,
开始,行动就是行动,
开始时间的最大值(开始时间),
结束。时间作为结束时间,
STRFTIME('%s',End.Time)-STRFTIME('%s',MAX(Start.Time))作为持续时间
从日志开始内部连接日志结束使用(用户)
从哪里开始。行动!='Done'和End.Action='Done'和Start.Time如果没有max(),则从某个随机行获取值。在当前的SQLite实现中,这是数据库在处理组时最后一次看到的行,因此使用升序时间戳存储这些行时,这恰好会产生您想要的行。但是,这种行为不能保证,即使在当前版本中,对查询的任何更改都可能使数据库以不同的顺序读取表
从具有次大时间戳的行中查找某些值的最可靠方法是使用相关子查询:
SELECT *,
strftime('%s', EndTime) - strftime('%s', StartTime) AS Duration
FROM (SELECT Time AS StartTime,
(SELECT Time
FROM Log AS L2
WHERE L2.User = Log.User
AND L2.Time > Log.Time
AND L2.Action = 'Done'
ORDER BY L2.Time ASC
LIMIT 1
) AS EndTime,
User,
Action
FROM Log
WHERE Action != 'Done');
我认为您很幸运,但是SQLite在SQL处理方面有一些奇怪的异常,这些异常实际上是被记录下来的。谢谢,但是我尝试使用max函数,有子查询和没有子查询,但我无法理解如何使用它。你能告诉我如何使用最大值使我的查询可靠吗?我喜欢使用极限值而不是最大值。我发现这很容易阅读。我只是问了另一个问题,这个问题的后续问题。你能看一下吗?