我的数据库(sqlite3)有两个包含以下模式的表:
CREATE TABLE log(d date, usr text, tag text, bytes int);
CREATE TABLE valid(tag text, filesize int);
假设我有以下示例数据:
d | usr | tag | bytes
--------------------------------
2012-01-19 | bob | foo | 990
2012-01-18 | bob | foo | 1000
2012-01-17 | joe | bar | 2000
2012-01-16 | joe | bar | 1800
2012-01-15 | joe | baz | 0
tag | size
-----------
foo | 1000
bar | 2000
我想检索导致用户无法访问有效文件中所有字节的最新事件列表。在上面的示例中,select应该产生2012-01-19 |鲍勃| foo | 990。
现在,我正在使用两个select语句来获得结果。第一个获取每个用户的最新事件,第二个检查是否访问了所有字节。
CREATE VIEW tmp AS
SELECT * FROM log JOIN (SELECT max(d) AS maxd, usr FROM log GROUP BY usr) AS
tmplog ON (tmplog.usr=log.usr and tmplog.maxd=log.d);
SELECT usr,d FROM tmp
WHERE tag IN (SELECT tag FROM valid) AND bytes NOT IN (SELECT size FROM valid);
有没有办法用一个选择或更有效的方式来做到这一点?
更新
在上面的示例中,查询不应检索用户“joe”,因为他最近的日志条目显示正在访问的完整文件。
答案 0 :(得分:1)
根据d
和usr
(其中tag
)查找最新的bytes < filesize
,然后选择与最近log
条匹配的d/usr/tag
条目}值:
SELECT log.*
FROM log
INNER JOIN ( SELECT usr, tag, MAX(d) AS d
FROM log
GROUP BY 1, 2) most_recent
ON most_recent.usr = log.usr
AND
most_recent.tag = log.tag
AND
most_recent.d = log.d
INNER JOIN valid
ON log.tag = valid.tag
WHERE log.bytes < valid.filesize;
答案 1 :(得分:1)
SELECT log.* FROM
log
JOIN
(SELECT usr,tag,MAX(d)
FROM log
GROUP BY usr,tag) log2
USING(usr,tag)
JOIN valid ON (log.tag = valid.tag)
WHERE d=`max(d)` AND bytes != valid.filesize
答案 2 :(得分:0)
Select
log.*
From log
Inner Join valid On valid.tag = log.tag
Where log.bytes < valid.size Order By log.d Desc
应该有效,但对我来说效率不高。
稍有不同的是,如果同一个用户有多个问题,它会为每个用户返回多行 - 你真的不想要这个吗?
答案 3 :(得分:0)
到目前为止我最接近的建议是:
加入log
和valid
以获取bytes <= size
所有行,并MAX(d)
找出tag
。
将结果集重新加入log
上的tag
&amp; d
获取与相应事件相关的所有行。
再次加入valid
,只获取bytes < size
所在的行。这对于过滤掉与大小匹配的字节的最大日期是必要的。
这是查询的外观:
SELECT
log.*
FROM log
INNER JOIN valid ON log.tag = valid.tag AND log.bytes < valid.size
INNER JOIN (
SELECT
log.tag,
MAX(log.d) AS d
FROM log
INNER JOIN valid ON log.tag = valid.tag AND log.bytes <= valid.size
GROUP BY
log.tag
) last
ON log.tag = last.tag AND log.d = last.d
以上假设在任何日期,特定标签只能有一个事件。否则,问题中提供的模式不允许在同一日期发生多个事件时确定哪个事件是最新事件。