SQL 在 LEFT JOIN 中获取 MAX 日期时间

Posted

技术标签:

【中文标题】SQL 在 LEFT JOIN 中获取 MAX 日期时间【英文标题】:SQL get MAX datetime in LEFT JOIN 【发布时间】:2020-10-12 20:09:10 【问题描述】:

我正在对表运行查询并进行左连接以尝试从左表中获取最新日期的记录,但它没有获取与日期时间列相关的其他值(用户和注释)

SELECT
    i.customer_sequence,
    i.due_date,
    
    MAX(cn.datetime) as notes_datetime,
    cn.user as notes_user,
    cn.notes as notes_notes
FROM
    billing_invoices i
LEFT JOIN customer_notes cn
    ON i.customer_sequence = cn.customer_seq
WHERE
    cn.type = 'Accounts' AND
    i.customer_sequence <> '0' AND
    i.status = 'Unpaid' AND
    i.directdebit <> 'Y'
GROUP BY
    i.customer_sequence
ORDER BY
    i.due_date DESC

【问题讨论】:

【参考方案1】:

聚合不是这里的解决方案。您想要连接表中的整行,因此建议进行过滤。如果您运行的是 mysql 8.0,我会推荐窗口函数:

SELECT *
FROM (
    SELECT
        i.customer_sequence,
        i.due_date,
        ROW_NUMBER() OVER(PARTITION BY i.customer_sequence ORDER BY cn.datetime DESC) rn,
        cn.datetime as notes_datetime,
        cn.user as notes_user,
        cn.notes as notes_notes
    FROM billing_invoices i
    LEFT JOIN customer_notes cn
        ON  i.customer_sequence = cn.customer_seq
        AND cn.type = 'Accounts'
    WHERE
        i.customer_sequence <> '0' AND
        i.status = 'Unpaid' AND
        i.directdebit <> 'Y'
) t
ORDER BY i.due_date DESC    

请注意,我将left joined 表上的条件从WHERE 子句移至连接的ON 子句(否则,这就像inner join)。


在早期版本中,一个选项是相关子查询:

SELECT
    i.customer_sequence,
    i.due_date,
    cn.datetime as notes_datetime,
    cn.user as notes_user,
    cn.notes as notes_notes
FROM billing_invoices i
LEFT JOIN customer_notes cn
    ON  i.customer_sequence = cn.customer_seq
    AND cn.type = 'Accounts'
    AND cn.datetime = (
        SELECT MAX(cn1.datetime)
        FROM customer_notes cn1
        WHERE i.customer_sequence = cn1.customer_seq AND cn1.type = 'Accounts'
    )
WHERE
    i.customer_sequence <> '0' AND
    i.status = 'Unpaid' AND
    i.directdebit <> 'Y'

【讨论】:

返回错误#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(PARTITION BY i.customer_sequence ORDER BY cn.datetime DESC) rn, cn.dat' at line 6 刚刚尝试了更新,从20 errors were found during analysis.开始出现更大的错误 @charlie:我想您的 MariaDB 版本不支持窗口函数(它们是在 10.3 中添加的)。我用没有窗口功能的解决方案更新了我的答案。 好吧,虽然似乎已经减慢了查询速度。有没有办法加快速度,或者循环billing_invoices 表并在每个循环中查询customer_notes 会更快吗? @charlie:您可以尝试利用customer_notes(customer_seq, type, datetime) 上的索引。您还可以升级到最新版本的 MariaDB 并使用窗口函数解决方案。

以上是关于SQL 在 LEFT JOIN 中获取 MAX 日期时间的主要内容,如果未能解决你的问题,请参考以下文章

EF Linq to Sql 多表left join查询并对结果group by分组之后进行count,max等处理

带有 LEFT JOIN 和 MAX 的 LibreOffice HSQLDB WHERE 子句?

SQL 使用 INNER JOIN 获取 MIN() 和 MAX()

Sql 两个表left join 查左表最时间最大的一条记录显示

SQL JOINSQL INNER JOIN 关键字SQL LEFT JOIN 关键字SQL RIGHT JOIN 关键字SQL FULL JOIN 关键字

使用来自多个数据集 SQL 的多个 LEFT JOIN