基于 MAX 时间戳的 SQL 内连接

Posted

技术标签:

【中文标题】基于 MAX 时间戳的 SQL 内连接【英文标题】:SQL Inner Join based on MAX of timestamp 【发布时间】:2016-03-18 02:18:38 【问题描述】:

修改过一次

两次修改:其余 9 个表格的表头除报告外始终称为“what”。

我有大约 10 个表,结构如下:

reports (165k rows)
+-----------+-----------+
| identifier| category  | 
+-----------+-----------+
| 1         | fixed     |
| 2         | wontfix   |
| 3         | fixed     |
| 4         | invalid   | 
| 5         | later     | 
| 6         | wontfix   | 
| 7         | duplicate | 
| 8         | later     | 
| 9         | wontfix   | 
+-----------+-----------+   
 status (300k rows, all identifiers from reports come up at least once)
+-----------+-----------+----------+
| identifier| time      | what     |
+-----------+-----------+----------+
| 1         | 12        | RESOLVED |
| 1         | 9         | NEW      |
| 2         | 7         | ASSIGNED |
| 3         | 10        | RESOLVED |
| 5         | 4         | REOPEN   |
| 7         | 9         | ASSIGNED |
| 4         | 9         | ASSIGNED |
| 7         | 11        | RESOLVED |
| 8         | 3         | NEW      |
| 4         | 3         | NEW      |
| 7         | 6         | NEW      |
+-----------+-----------+----------+

 priority (300k rows, all identifiers from reports come up at least once)
+-----------+-----------+----------+
| identifier| time      | what     |
+-----------+-----------+----------+
| 3         | 12        | LOW      |
| 1         | 9         | LOW      |
| 9         | 2         | HIGH     |
| 8         | 7         | HIGH     |
| 3         | 10        | HIGH     |
| 5         | 4         | MEDIUM   |
| 4         | 9         | MEDIUM   |
| 4         | 3         | LOW      |
| 7         | 9         | LOW      |
| 7         | 11        | HIGH     |
| 8         | 3         | LOW      |
| 6         | 12        | MEDIUM   |
| 7         | 6         | LOW      |
| 6         | 9         | HIGH     |
| 2         | 6         | HIGH     |
| 2         | 1         | LOW      |
+-----------+-----------+----------+

我需要的是:

 reportsfinal (165k rows)
+-----------+-----------+--------------+------------+
| identifier| category  | what11       |  what22    |
+-----------+-----------+--------------+------------+
| 1         | fixed     | RESOLVED     | LOW        |
| 2         | wontfix   | ASSIGNED     | HIGH       |
| 3         | fixed     | RESOLVED     | LOW        |
| 4         | invalid   | ASSIGNED     | MEDIUM     |
| 5         | later     | REOPEN       | MEDIUM     |
| 6         | wontfix   |              | MEDIUM     |
| 7         | duplicate | RESOLVED     | HIGH       |
| 8         | later     | NEW          | HIGH       |
| 9         | wontifx   |              | HIGH       |
+-----------+-----------+--------------+------------+

也就是说,reports(查询后 = reportsfinal)作为基础表,我必须从其他 9 个表中添加一到两列。 identifier 是关键,但在某些表中,identifier 出现多次。在这些情况下,我只想使用时间最长的条目。 我尝试了几个查询,但没有一个有效。如果可能的话,我想使用这种方法运行一个查询以从其他 9 个表中获取不同的列。

我根据以下答案尝试了什么:

select  T.identifier,
        T.category,
        t.what AS what11,
        t.what AS what22 from (
     select R.identifier,
     R.category,
     COALESCE(S.what,'NA')what,
     COALESCE(P.what,'NA')what,
     ROW_NUMBER()OVER(partition by R.identifier,R.category ORDER by (select null))RN
     from reports R 
     LEFT JOIN bugstatus S
     ON S.identifier = R.identifier
     LEFT JOIN priority P
     ON P.identifier = s.identifier

     GROUP BY R.identifier,R.category,S.what,P.what)T
     Where T.RN = 1
     ORDER BY T.identifier;

这给出了错误:

Error: near "(": syntax error.

【问题讨论】:

【参考方案1】:

对于每个关联的表,只需使用基于子查询的谓词来识别特定的时间戳...

单字母标记 r、s 和 p 分别是表报告、状态和优先级的定义别名

Select r.Identifier, r.category,
   coalesce(s.what, 'NA') status,
   coalesce(p.what, 'NA') priority
From reports r
  left join status s
     on s.identifier = r.identifier
        and s.time =
           (Select max(time) from status 
            where identifier = r.identifier)
  left join priority p
     on p.identifier = r.identifier
        and p.time =
           (Select max(time) from priority 
            where identifier = r.identifier);

问题:为什么将列从Statuspriority 重命名为What?您不妨将其命名为 somethingdatainformation。至少最初的名称(statusprio)传达了一些信息。What 这个词毫无意义。

注意。我撤消了对what11what12 别名的编辑,因为这些名称毫无意义。

【讨论】:

我收到“错误:列名不明确:时间” 我明白你关于标题“什么”的观点。我没有这样定义它们,它们在 csv 文件中是这样的。但你是对的,在创建 SQLite 数据库时,我本可以给它们起更有意义的名称。查询现在已经运行了 4 个小时,但仍未完成。我认为必须有一个查询可以更快地获取数据?@Charles Bretana 外键有索引吗? 对不起,我无法回答。这些表格如我的问题中所述。在报告表中,主键是“标识符”。在其他表中,唯一标识符将是“标识符”和“时间”的组合。@PilotBob 如果您可以联系 dbo 的任何人,请向他们询问是否可以在 status.timepriority.time 上添加索引。此外,如果它是 SQL Server,或者如果它使用聚集索引的任何数据库,我会在这两个字段的组合上创建主键聚集索引(identifier, time)。(这是 SQL 服务器,或 Oracle 或 mysql ??)【参考方案2】:

基本上你需要选择列表中的相关子查询。

从臀部,类似于:

Select a.Identifier
,a.Category
,(select process
    from status where status.identifier = a.Identifer order by time desc limit 1) Process
,(select prio
    from priority where priorty.identifier = a.Identifer order by time desc limit 1) prio
From Reports a

【讨论】:

@peter:“a”代表什么?是a=报告吗?此外 TOP 1 在 SQLite 中不起作用,我读到 LIMIT 1 起作用。像这样我没有收到错误,但查询仍在运行(我有 300k 行):'Select reports.identifier,reports.current_resolution,reports.current_status,(select what from bugstatus where bugstatus.identifier = reports.identifier按时间戳顺序排列 LIMIT 1) 什么,(从优先级中选择什么,其中 priority.identifier = reports.identifier 按时间戳顺序排列 LIMIT 1) 从报告中选择什么;` 是的,我说它是从臀部,我使用 T-SQL,我认为你使用 Sqllite.. 所以限制 1 似乎是等价的。是的,我打算将 Reports 别名为 A,但没有。你说它有效还是无效? 是的,我正在使用 SQLite。那么,我需要在查询结束时使用“From reports a”吗?我的提案的其余部分是否正确?非常感谢。@PilotBob 是的,这应该使报告...或者您可以在查询的其余部分将其从 a 更改为报告。我认为您的编辑看起来不错。 我对其进行了编辑以添加别名并使用 sqlite limit 1 语法。【参考方案3】:

根据您的假设数据使用 Row_number

select  T.identifier,
        T.category,
        what AS what11,
        what AS what22 from (
     select R.identifier,
     r.category,
     COALESCE(S.what,'NA')what,
     COALESCE(P.what,'NA')what,
     ROW_NUMBER()OVER(partition by R.identifier,r.category ORDER by (select null))RN
     from reports R left join status S
     ON S.identifier = R.identifier
     LEFT JOIN Priority P
     ON P.identifier = s.identifier

     GROUP BY R.identifier,r.category,S.what,P.what)T
     Where T.RN = 1
     ORDER BY T.identifier

【讨论】:

T 代表什么或在哪里定义? "ORDER by (select null))RN" RN 代表什么或它在哪里定义?非常感谢! 我已用作派生表,而 T 只不过是别名。 RN 是 Row_number 并选择 Null 用于订购目的@JohnDavison 1) 您可以互换使用大小写字母作为别名和表名。这有关系吗? 2) 表格中没有明确的“NA”,而是空白。代码是否必须更改? 3) 我将后续表格状态和优先级的标题更改为“什么”。如果所有标题都被称为“什么”,这是一个问题吗?我收到错误消息:“错误:靠近”(“:语法错误”。@mohan111 NA 只不过是 NULL,您可以将其更改为 null 并出现语法错误,正确给出列名 对于初始问题中的新标题,编辑后的代码是否正确?别名是 r 还是 R 有关系吗? @mohan111

以上是关于基于 MAX 时间戳的 SQL 内连接的主要内容,如果未能解决你的问题,请参考以下文章

带有在单独表中定义的时间戳的 SQL EXCLUDE 记录

CouchDB 查询以获取具有 MAX 时间戳的文档

SQL时间戳的使用

SQL查询以获取具有不同时间戳的多行

在sqlserver中怎么将一个时间字符串值转换成时间戳的数字形式

计算同一张表中SQL中两个时间戳的差值