【问题标题】:Show only most recent date from joined MySQL table仅显示加入的 MySQL 表中的最近日期
【发布时间】:2009-09-02 15:15:12
【问题描述】:

我有 2 个表,一个“文档”表和一个“内容”表。它们看起来像这样(简化):

document table:
docID
docTitle

content table:
contentID
docID
dateAdded
content

对于每个内容更改,都会在“内容”表中插入一条新记录。这样就有了所有变化的完整历史。我想获取所有文档的列表,并加入最新的内容。它应该返回 docID、docTitle 和具有最新“dateAdded”值的相关内容记录。我的大脑现在让我失望了,我该如何创建这个连接?

【问题讨论】:

  • 也许将此问题重命名为更具描述性的名称,例如“仅显示连接表中的最新日期”?
  • @Gorgapor:好电话,我已经更新了标题。

标签: sql mysql join


【解决方案1】:

你能不能只做一个简单的连接,按添加日期排序,只抓取第一条记录?

SELECT docTable.docId, docTable.docTitle from docTable
INNER JOIN content ON content.docID = docTable.contentID
WHERE docTable.docId = <some id>
ORDER BY content.dateAdded DESC

【讨论】:

  • 我想你希望 order by 是 DESC,所以最新版本是第一个。此外,如果您添加“LIMIT 1”,您将获得一行。
  • 您对订购的权利。至于限制,你也对,我只是把它省略了,因为我不确定数据库技术。该命令可能会有所不同(据我所知)。
【解决方案2】:

这可以通过子查询来完成:

SELECT d.docID, docTitle, c.dateAdded, c.content
FROM document d LEFT JOIN content c ON c.docID = d.docID
WHERE dateAdded IS NULL
    OR dateAdded = (
        SELECT MAX(dateAdded)
        FROM content c2
        WHERE c2.docID = d.docID
    )

这称为"groupwise maximum" 查询

编辑:使查询返回所有文档行,如果没有相关内容,则返回 NULL。

【讨论】:

  • 感谢您的名字。每当我有一个 SQL 问题时,我永远不知道谷歌是为了什么,这使得找到解决方案变得更加困难。 :)
  • 当文档没有内容记录时,此查询是否有效?我仍然希望它列出文档,并为 dateAdded 和 content 字段返回 null。
  • 我会将 LIMIT 1 添加到子查询中。 content 表中可以有多个具有相同dateAdded 值的记录。那将导致失败。 MySQL 存储 DATETIME 的精度仅为秒,这确实可能发生。更好的解决方案是按一些唯一的顺序列排序,无论是主键,还是存储更改顺序的任意列,即使在日期时间精度不够。
【解决方案3】:

用途:

SELECT t.docid, 
       t.docTitle, 
       mc.dateAdded, 
       mc.content
  FROM DOCUMENT t
  JOIN (SELECT c.docid,
               c.content,
               MAX(c.dateAdded)
          FROM CONTENT c
      GROUP BY c.docid, c.content) mc ON mc.docid = t.docid 
                                     AND mc.dateadded = t.dateadded

这应该比相关子查询更快。

当文档没有内容记录时的替代方案:

   SELECT t.docid, 
          t.docTitle, 
          mc.dateAdded, 
          mc.content
     FROM DOCUMENT t
LEFT JOIN (SELECT c.docid,
                  c.content,
                  MAX(c.dateAdded)
             FROM CONTENT c
         GROUP BY c.docid, c.content) mc ON mc.docid = t.docid 
                                     AND mc.dateadded = t.dateadded

【讨论】:

    【解决方案4】:

    这是一个2查询解决方案:

    第一个查询:

    select docID, max(dateadded) from [TblContent] group by docID
    

    第二次查询:

    select [TblDocument].* from [TblDocument]  
    inner join [TblDocument] on [TblDocument].[Docid]=[FirstQuery].[DocID]
    

    【讨论】:

    • 这需要对每一行单独查询,而不仅仅是两个查询。
    【解决方案5】:

    试试这个:

    select d.id, d.docTitle, MAX(c.dateAdd)
    from document_table d
    left join content_table c
    on d.id = c.docId
    group by d.id
    

    以下是其背后的思路:假设文档表有与内容相关的记录A(1、2、3、4)和与(5、6、7、8)相关的B

    document        content
    
    A               1
                2
                        3
                4
    
    B               5
                6
                7
                8
    

    一个带有 max(dateadded) 的内部连接会给你

    document        content     max(dateadded)
    
    A               1           1-1-2009...
    
    A               2           1-1-2009...
    
    A               3           1-1-2009...
    
    A               4           1-1-2009...
    
    B               5           2-1-2009...
    
    B               6           2-1-2009...
    
    B               7           2-1-2009...
    
    B               8           2-1-2009...
    

    按文档ID分组后,您将获得

    document    content     max(dateadded)
    
    A           1           1-1-2009...
    
    B           5           2-1-2009...
    

    注意:内容 id 不必与添加的最大日期的 id 匹配

    【讨论】:

    • 是否可以通过将其更改为外部连接来返回没有关联内容记录的文档,或者这会改变行为吗?此外,这是否可以通过将它们包含在选择中来返回 contentID 和内容字段,还是会搞砸?
    • 这是我的 Sql 吗?因为如果不是,则取决于数据库,您可能无法选择任何不在 group by 子句中的内容。
    • 你可以做左连接,但你不能把 contentID 列放在那里。
    • 此解决方案未按要求“返回...关联的内容记录”。
    • 如果您只想显示每个文档的最后更新时间,这可以正常工作 - 然后您可以使用 MAX(date),但它不能保证内容表中其他列的内容。
    猜你喜欢
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-13
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多