【问题标题】:How do I create a common table expression with two derived tables如何使用两个派生表创建公用表表达式
【发布时间】:2021-02-22 22:57:56
【问题描述】:

所以我尝试用两个派生表创建这个 CTE。我的第一个派生表将显示 500 范围内的帐号、帐号描述。 CTE 中的第二个派生表 - 应列出发票总数大于 1000 的帐号、发票总数和发票 ID。

现在我开始分别创建这两个表,以确保我知道自己在做什么。他们是这样工作的:

SELECT AccountNo, 
    AccountDescription
FROM Accounts
WHERE AccountNo BETWEEN 500 and 599

SELECT Accounts.AccountNo, 
    Invoices.InvoiceTotal, 
    Invoices.InvoiceID
FROM Accounts 
    JOIN InvoiceLineItems
        ON Accounts.AccountNo = InvoiceLineItems.AccountNo
    JOIN Invoices
        ON InvoiceLineItems.InvoiceID = Invoices.InvoiceID
WHERE Invoices.InvoiceTotal >= 1000

现在,当我尝试将它们变成 CTE 时,我的最佳尝试如下所示:

WITH Accounts500to599 AS
(SELECT AccountNo, 
    AccountDescription
FROM Accounts
WHERE AccountNo BETWEEN 500 and 599
ORDER BY Accounts.AccountNo),

InvoicesAbove1000 AS 
(SELECT Accounts.AccountNo, 
    Invoices.InvoiceTotal, 
    Invoices.InvoiceID
FROM Accounts 
    JOIN InvoiceLineItems
        ON Accounts.AccountNo = InvoiceLineItems.AccountNo
    JOIN Invoices
        ON InvoiceLineItems.InvoiceID = Invoices.InvoiceID
WHERE Invoices.InvoiceTotal >= 1000
ORDER BY Accounts.AccountNo)

现在我的最终目标是显示发票大于平均发票总额的帐户,这应该很简单,但在创建这些 CTE 时我还有很多东西要学。

任何建议将不胜感激。谢谢。

【问题讨论】:

    标签: sql sql-server common-table-expression derived-table


    【解决方案1】:

    像对待任何其他表(或视图)一样对待 CTE。它会创建一个虚拟表以供使用。

    例如,在你上面,你可以这样做

    WITH Accounts500to599 AS
    (SELECT AccountNo, 
        AccountDescription
    FROM Accounts
    WHERE AccountNo BETWEEN 500 and 599
    -- ORDER BY Accounts.AccountNo -- Note - removed the order by
    ),
    
    InvoicesAbove1000 AS 
    (SELECT Accounts.AccountNo, 
        Invoices.InvoiceTotal, 
        Invoices.InvoiceID
    FROM Accounts 
        JOIN InvoiceLineItems
            ON Accounts.AccountNo = InvoiceLineItems.AccountNo
        JOIN Invoices
            ON InvoiceLineItems.InvoiceID = Invoices.InvoiceID
    WHERE Invoices.InvoiceTotal >= 1000
    --ORDER BY Accounts.AccountNo   -- Note - removed the order by
    )
    
    SELECT A.AccountNo, A.AccountDescription, AVG(I.InvoiceTotal) AS AvgInvoiceTotal
    FROM   Accounts500to599 A
           INNER JOIN InvoicesAbove1000 I ON A.AccountNo = I.AccountNo
    GROUP BY A.AccountNo, A.AccountDescription
    

    这并不能回答您的“发票高于平均水平”,因为当您已经排除了小于 1000 美元的发票时,这实际上意味着什么存在一些问题,但上面给出了如何使用它们的示例。

    请注意,数据的顺序无关紧要(就像普通表一样) - 因此我在 CTE 中注释掉了 ORDER BY 子句。

    传统的 CTE 在功能上也等同于 FROM 子句中的子查询 - 所以上面类似于

    SELECT A.AccountNo, A.AccountDescription, AVG(I.InvoiceTotal) AS AvgInvoiceTotal
    FROM   (SELECT AccountNo, 
                   AccountDescription
            FROM Accounts
            WHERE AccountNo BETWEEN 500 and 599
           ) A
           INNER JOIN 
          (SELECT Accounts.AccountNo, 
              Invoices.InvoiceTotal, 
             Invoices.InvoiceID
           FROM Accounts 
               JOIN InvoiceLineItems
                    ON Accounts.AccountNo = InvoiceLineItems.AccountNo
               JOIN Invoices
                    ON InvoiceLineItems.InvoiceID = Invoices.InvoiceID
          WHERE Invoices.InvoiceTotal >= 1000
        ) I ON A.AccountNo = I.AccountNo
    GROUP BY A.AccountNo, A.AccountDescription
    

    【讨论】:

      【解决方案2】:

      作为对 seanb 答案的扩展,您可以通过以下方式尝试使您的发票高于平均发票金额。看看WHERE

      ;WITH Accounts500to599 AS (
          SELECT
              AccountNo, 
              AccountDescription
          FROM AS Accounts
          WHERE
              AccountNo BETWEEN 500 and 599
      ),
      InvoicesAbove1000 AS (
          SELECT
              Accounts.AccountNo, 
              Invoices.InvoiceTotal, 
              Invoices.InvoiceID
          FROM Accounts 
              JOIN InvoiceLineItems
                  ON Accounts.AccountNo = InvoiceLineItems.AccountNo
              JOIN Invoices
                  ON InvoiceLineItems.InvoiceID = Invoices.InvoiceID
          WHERE 
              Invoices.InvoiceTotal >= 1000
      )
      SELECT
          Accounts500to599.AccountNo,
          Accounts500to599.AccountDescription,
          InvoicesAbove1000.InvoiceID,
          InvoicesAbove1000.InvoiceTotal
      FROM Accounts500to599
      INNER JOIN InvoicesAbove1000
          ON Accounts500to599.AccountNo = InvoicesAbove1000.AccountNo
      WHERE InvoicesAbove1000.InvoiceTotal > (
          
          SELECT 
              AVG( InvoiceTotal )
          FROM Accounts AS a
          INNER JOIN InvoiceLineItems l
              ON a.AccountNo = l.AccountNo
          INNER JOIN Invoices i
              ON l.InvoiceID = i.InvoiceID
          WHERE
              a.AccountNo BETWEEN 500 AND 599
              AND i.InvoiceTotal > 1000
      
      )
      ORDER BY
          Accounts500to599.AccountNo;
      

      【讨论】:

        猜你喜欢
        • 2012-05-12
        • 2010-09-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多