以下代码列出了所有发票,我只想要供应商提供的最早发票:
SELECT DISTINCT vendor_name, i.invoice_number AS OLDEST_INVOICE,
MIN(i.invoice_date), i.invoice_total
FROM vendors v
JOIN invoices i
ON i.vendor_id = v.vendor_id
GROUP BY vendor_name, invoice_number, invoice_total
ORDER BY MIN(i.invoice_date);
答案 0 :(得分:1)
TDQD的时间 - 测试驱动的查询设计
每个供应商的发票的最短日期由:
SELECT vendor_id, MIN(invoice_date) AS invoice_date
FROM invoices
GROUP BY vendor_id
相应的最低发票编号(假设在{1}}是真正的DATE且没有时间成分的情况下,可能在供应商开具发票的第一天发送了多张发票;如果DATE包含时间成分,第二个MIN()可能是不必要的),是:
invoice_date
您可以将此表达式与其他表连接以满足您的查询要求:
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
毫无疑问,还有其他方法来设计它。请注意,这些子查询都不是相关的子查询。
TDQD纯粹是名义上的;没有DBMS在检查这些查询是否在语法上有效时更加困难,更不用说返回正确答案了。 OTOH,这是一种标准技术。
如果您希望在GROUP BY子句中列出大量列,则可以通过让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
子查询返回相关的发票列来最终加入invoices
。我不喜欢写出很多列名 - 但如果我担心性能,我会测量它是否有显着差异。
您可能会发现有一个OLAP函数/查询可以更快地完成工作。
答案 1 :(得分:1)
我们将使用ROW_NUMBER()
按供应商的日期对发票进行“排名”,然后仅选择每个供应商最早的发票:
SELECT vendor_name, invoice_number AS oldest_invoice, invoice_date, invoice_total
FROM vendors v
INNER JOIN (SELECT invoices.*,
ROW_NUMBER() OVER (PARTITION BY vendor_id ORDER BY invoice_date ASC)
AS rn
FROM invoices) i
ON i.vendor_id = v.vendor_id
AND
i.rn = 1;
答案 2 :(得分:0)
请改为尝试:
SELECT DISTINCT
v.vendor_name,
i.invoice_number AS OLDEST_INVOICE,
i2.MinDate,
i.invoice_total
FROM vendors v
INNER JOIN invoices i ON i.vendor_id = v.vendor_id
INNER JOIN
(
SELECT
invoice_number ,
MIN(i.invoice_date) MinDate
FROM invoices
GROUP BY invoice_number
) i2 ON i.invoice_number = i2.invoice_number
AND i.invoice_date = i2.MinDate
ORDER BY i2.MinDate;
答案 3 :(得分:0)
HAVING
不会在这里工作吗?
SELECT DISTINCT vendor_name, i.invoice_number AS OLDEST_INVOICE,
MIN(i.invoice_date), i.invoice_total
FROM vendors v
JOIN invoices i
ON i.vendor_id = v.vendor_id
GROUP BY vendor_name, invoice_number, invoice_total
HAVING i.invoice_date = MIN (i.invoice_date)
ORDER BY MIN(i.invoice_date);