SQL联合查询 - 引用派生表的别名

时间:2018-01-02 10:32:56

标签: mysql sql

我有一个复杂的聚合函数查询,它生成一个结果集,并且必须使用包含该结果集的总计和平均值的单行进行修改。

我的想法是为结果集分配别名,然后在UNION ALL语句之后在第二个查询中使用该别名。

但是,我无法在UNION ALL语句之后的后续SELECT语句中成功使用别名。

为了简单起见,我不会在这里发布原始查询,只是我试过的变种的简化列表:

SELECT * FROM fees AS Test1 WHERE Percentage = 15
UNION ALL
(SELECT * FROM fees AS Test2 WHERE Percentage > 15)
UNION ALL
(SELECT * FROM (SELECT * FROM fees AS Test3 WHERE Percentage < 10) AS Test4)
UNION ALL
SELECT * FROM Test3

结果是:

MySQL said: Documentation
#1146 - Table 'xxxxxx.Test3' doesn't exist

如果最后一个查询引用表Test1,Test2或Test4,结果是相同的。

那么,我应该如何在早期查询中为结果集/派生表分配别名,并在后面的查询中使用相同的别名,所有这些都在UNION查询中?

修订:

我的主要疑问是:

SELECT

COALESCE(referrers.name,order_items.ReferrerID),

SUM(order_items.quantity) as QtySold,

ROUND(SUM((order_items.quantity*order_items.price+order_items.shippingcosts)/((100+order_items.vat)/100)), 2) as TotalRevenueNetto,

ROUND(100*SUM(order_items.quantity*order_items.purchasepricenet)/SUM((order_items.quantity*order_items.price+order_items.shippingcosts)/((100+order_items.vat)/100)), 1) as PurchasePrice,

ROUND(100*SUM(order_items.quantity*COALESCE(order_items.calculatedfee,0)+order_items.quantity*COALESCE(order_items.calculatedcost,0))/SUM((order_items.quantity*order_items.price+order_items.shippingcosts)/((100+order_items.vat)/100)), 1) as Costs,

ROUND(100*SUM(order_items.calculatedprofit) / SUM( (order_items.quantity*order_items.price + order_items.shippingcosts)/((100+order_items.vat)/100) ) , 1) as Profit,

COALESCE(round(100*Returns.TotalReturns_Qty/SUM(order_items.quantity),2),0) as TotalReturns

FROM order_items LEFT JOIN (SELECT order_items.ReferrerID as ReferrerID, sum(order_items.quantity) as TotalReturns_Qty FROM order_items WHERE OrderType='returns' and OrderTimeStamp>='2017-12-1 00:00:00' GROUP BY order_items.ReferrerID) as Returns ON Returns.ReferrerID = order_items.ReferrerID LEFT JOIN `referrers` on `referrers`.`referrerId` = `order_items`.`ReferrerID`

WHERE ( ( order_items.BundleItemID in ('-1', '0') and order_items.OrderType in ('order', '') ) or ( order_items.BundleItemID is NULL and order_items.OrderType = 'returns' ) ) and order_items.OrderTimestamp >= '2017-12-1 00:00:00'

GROUP BY order_items.ReferrerID
ORDER BY referrers.name ASC

我想通过以下方式对上面的查询产生的所有行进行总计:

SELECT 'All marketplaces', SUM(QtySold), SUM(TotalRevenueNetto), AVG(PurchasePrice), AVG(Costs), AVG(Profit), AVG(TotalReturns) FROM PrimaryQuery

我想用一个查询来做这件事。

5 个答案:

答案 0 :(得分:1)

您的查询写得很好。您可以通过使用带有伪GROUP BY子句和WITH ROLLUP子句的周围查询来获取总线:

SELECT 
  COALESCE(Referrer, 'All marketplaces'),
  SUM(QtySold) AS QtySold,
  SUM(TotalRevenueNetto) AS TotalRevenueNetto,
  AVG(PurchasePrice) AS PurchasePrice,
  AVG(Costs) AS Costs,
  AVG(Profit) AS Profit,
  AVG(TotalReturns) AS TotalReturns
FROM 
(
  SELECT
    COALESCE(referrers.name,order_items.ReferrerID) AS Referrer,
    SUM(order_items.quantity) AS QtySold,
  ...
) PrimaryQuery
GROUP BY Referrer ASC WITH ROLLUP;

答案 1 :(得分:0)

您有错误,因为UNION中涉及的每个查询都不知道其他查询的别名。

DB Engine在您的情况下执行4次查询,然后使用UNION操作粘贴它们。

您的真实表格为fees。 Test3是第三个查询中使用的别名。

如果要处理UNION操作的结果,则必须将查询封装在MAIN查询中。

答案 2 :(得分:0)

看起来你需要像下面这样的东西。请尝试

SELECT * FROM fees AS Test2 WHERE Percentage >= 15
UNION ALL
SELECT * FROM fees AS Test3 WHERE Percentage < 10

答案 3 :(得分:0)

您不能使用基于子查询的表别名(不在外部联合选择的范围内)您必须重复代码,例如:

SELECT * FROM fees AS Test1 WHERE Percentage = 15
UNION ALL
SELECT * FROM fees AS Test2 WHERE Percentage > 15
UNION ALL
SELECT * FROM (
    SELECT * FROM fees AS Test3 WHERE Percentage < 10
    ) AS Test4
UNION ALL
SELECT * FROM fees AS Test3 WHERE Percentage < 10

答案 4 :(得分:0)

我不完全确定你要解决的是什么,但我想如下:

假设&#39;主要&#39;查询:

SELECT    T1.ID
,         Sum(total_grade)/COUNT(subjects) as AverageGrade
FROM      A_Table T1
JOIN      AnotherTable T2
      ON  T2.id = T1.id
GROUP BY  T1.ID

您需要子结果集,而不必继续查询相同的数据。

编辑:我错误地认为下面提到的链接文档和方法适用于当前版本的mySQL。但它是未来版本的草稿,CTE目前支持

在没有CTE支持的情况下,我可能只是将结果集插入临时表中。类似的东西:

CREATE TABLE TEMP_TABLE(ID INT, AverageGrade DECIMAL(15, 3))

INSERT INTO TEMP_TABLE
        SELECT    T1.ID
        ,         Sum(total_grade)/COUNT(subjects) as AverageGrade
        FROM      A_Table T1
        JOIN      AnotherTable T2
              ON  T2.id = T1.id
        GROUP BY  T1.ID

SELECT ID, AverageGrade FROM TEMP_TABLE WHERE AverageGrade > 5
UNION ALL
SELECT COUNT(ID) AS TotalCount, SUM(AverageGrade) AS Total_AVGGrade FROM TEMP_TABLE

DROP TABLE TEMP_TABLE

(免责声明:我对mySQL不太熟悉,这里可能会出现一些语法错误。但总体思路应该很明确。)

当然,也就是说,如果我 这样做,那么可能有更好的方法来实现同样的目标。请参阅Thorsten Kettner对此事的评论。

(以前的答案假设CTE是一个可能性:)

CTE方法如下:

WITH CTE AS
(
    SELECT    T1.ID
    ,         Sum(total_grade)/COUNT(subjects) as AverageGrade
    FROM      A_Table T1
    JOIN      AnotherTable T2
          ON  T2.id = T1.id
    GROUP BY  T1.ID
)

SELECT ID, AverageGrade FROM CTE WHERE AverageGrade > 5
UNION ALL
SELECT COUNT(ID) AS TotalCount, SUM(AverageGrade) AS Total_AVGGrade FROM CTE