【问题标题】:How can I select the set of rows where each item has the greatest timestamp?如何选择每个项目具有最大时间戳的行集?
【发布时间】:2015-12-09 01:01:15
【问题描述】:

使用 Sqlite,我想获取具有最大时间戳的行的集合。该表包含项目的属性,即键值对和时间戳。我想为每个属性选择最新的值。

考虑以下简化的架构和数据:

CREATE TABLE Properties (thing VARCHAR,
                         key VARCHAR,
                         value VARCHAR,
                         timestamp INT);
INSERT INTO Properties VALUES ("apple", "color", "red", 0);
INSERT INTO Properties VALUES ("apple", "taste", "sweet", 0);
INSERT INTO Properties VALUES ("apple", "size", "small", 0);
INSERT INTO Properties VALUES ("watermelon", "taste", "sweet", 0);
INSERT INTO Properties VALUES ("watermelon", "size", "large", 0);
INSERT INTO Properties VALUES ("watermelon", "color", "pink", 1);
INSERT INTO Properties VALUES ("watermelon", "color", "green", 0);

我想为 thing="watermelon" 编写一个查询,返回:

taste|sweet
size|large
color|pink

注意有两行key="color",查询返回timestamp 值最大的行。此外,一个属性的最大 timestamp 可能与另一个属性不同。

到目前为止我尝试过的包括:

获取thing="watermelon"的属性集:

SELECT DISTINCT(key) FROM Properties WHERE thing='watermelon';

thing="watermelon" 获取key="color" 的最新值:

SELECT * 
FROM Properties
WHERE thing='watermelon'
  AND key='color'
ORDER BY timestamp DESC
LIMIT 1;

但我不知道如何将两者结合起来。我可能是从命令式编程的角度来解决这个问题的,这就是为什么我会感谢帮助。

【问题讨论】:

    标签: sql sqlite greatest-n-per-group


    【解决方案1】:

    在 SQLite 3.7.11 或更高版本中,您可以简单地使用 MAX() 从组中选择一行:

    SELECT key, value, MAX(timestamp)
    FROM Properties
    WHERE thing = 'watermelon'
    GROUP BY key;
    

    【讨论】:

    • SQLite 如何知道选择对应于最大时间戳的value?如果查询是select key, value, max(timestamp), min(timestamp),那么查询会返回哪个value
    • 然后它随机选择这两行之一。
    • 它不会仍然在您的查询中选择一个随机的value 行吗?我不确定sqlite,但这是mysql中的常见错误,因为根据mysql文档,允许引擎在选择不在组中的列时返回一个随机值,但实际上它通常返回与之关联的列最大/最小等,所以人们认为这就是它的工作原理。但是这种行为可能会逐个版本地改变。 stackoverflow.com/questions/1752556/…
    • SQLite 保证其他列的值来自与 MIN()/MAX() 匹配的行。
    • 当有MIN()/MAX()时,选择is not arbitrary
    【解决方案2】:

    调整找到here的查询,我想出了以下内容:

    SELECT a.* 
    FROM Properties AS a 
    INNER JOIN (
      SELECT key, MAX(timestamp) AS max_timestamp 
      FROM Properties 
      WHERE thing='watermelon' 
      GROUP BY key) b 
    ON a.key = b.key AND a.timestamp = b.max_timestamp 
    WHERE thing='watermelon';
    

    似乎有效,但我对 cme​​ts 这个查询的优点/缺点感兴趣。

    【讨论】:

      【解决方案3】:

      使用HAVING 获得简单易读的解决方案:

      SQLFiddleDemo

      SELECT *
      FROM Properties
      WHERE thing = "watermelon"
      GROUP BY thing, key
      HAVING timestamp = MAX(timestamp)
      

      【讨论】:

      • 投反对票有什么特别的原因吗?如果这个解决方案有什么错误,我会很高兴听到它。
      猜你喜欢
      • 2021-10-31
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      • 2013-06-24
      • 1970-01-01
      • 2020-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多