2

以下代码列出了所有发票,我只想要供应商的最旧发票:

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);
4

4 回答 4

2

我们将使用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;
于 2012-11-04T22:36:36.787 回答
1

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 函数/查询可以更快地完成这项工作。

于 2012-11-04T22:18:31.100 回答
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;
于 2012-11-04T21:24:34.780 回答
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);
于 2012-11-04T21:30:40.313 回答