我有一个复杂的聚合函数查询,它生成一个结果集,并且必须使用包含该结果集的总计和平均值的单行进行修改。
我的想法是为结果集分配别名,然后在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
我想用一个查询来做这件事。
答案 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