TDQD 的时间——测试驱动的查询设计
每个供应商开具发票的最短日期为:
SELECT vendor_id, MIN(invoice_date) AS invoice_date
FROM invoices
GROUP BY vendor_id
相应的最小发票编号(假设在为供应商开具发票的第一天可能已经发送了多张发票,如果invoice_date
是没有时间组件的真实 DATE;如果 DATE 包含时间组件,则第二个 MIN() 可能是不必要的),是:
SELECT vendor_id, MIN(invoice_number) AS invoice_number
FROM invoices AS i
JOIN (SELECT vendor_id, MIN(invoice_date) AS invoice_date
FROM invoices
GROUP BY vendor_id
) AS j ON j.vendor_id = i.vendor_id AND j.invoice_date = i.invoice_date
GROUP BY vendor_id
您可以将此表达式与其他表连接以满足您的查询要求:
SELECT v.*, i.*
FROM vendors AS v
JOIN (SELECT vendor_id, MIN(invoice_number) AS invoice_number
FROM invoices AS i
JOIN (SELECT vendor_id, MIN(invoice_date) AS invoice_date
FROM invoices
GROUP BY vendor_id
) AS j ON j.vendor_id = i.vendor_id AND j.invoice_date = i.invoice_date
GROUP BY vendor_id
) AS inv_info ON v.vendor_id = inv_info.vendor_id
JOIN invoices AS i ON i.invoice_number = inv_info.invoice_number
毫无疑问,还有其他设计方法。请注意,这些子查询都不是相关子查询。
TDQD 纯粹是名义上的;没有 DBMS 为检查这些查询在语法上是否有效而烦恼,更不用说返回正确的答案了。OTOH,这是一种标准技术。
invoices
如果您喜欢在 GROUP BY 子句中列出大量列,则可以通过让inv_info
子查询返回相关发票列而无需最终连接。我不喜欢写出很多列名——但如果我担心性能,我会衡量它是否会产生显着差异。
您可能会发现有一个 OLAP 函数/查询可以更快地完成这项工作。