SQL:选择某种类型的最新事件

时间:2012-01-20 00:30:24

标签: sql sqlite

我的数据库(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”,因为他最近的日志条目显示正在访问的完整文件。

4 个答案:

答案 0 :(得分:1)

根据dusr(其中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)

到目前为止我最接近的建议是:

  1. 加入logvalid以获取bytes <= size所有行,并MAX(d)找出tag

    < / LI>
  2. 将结果集重新加入log上的tag&amp; d获取与相应事件相关的所有行。

  3. 再次加入valid,只获取bytes < size所在的行。这对于过滤掉与大小匹配的字节的最大日期是必要的。

  4. 这是查询的外观:

    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
    

    以上假设在任何日期,特定标签只能有一个事件。否则,问题中提供的模式不允许在同一日期发生多个事件时确定哪个事件是最新事件。