Subquery
CTE 和子查詢的非常奇怪的結果
WITH t1 AS (SELECT a.id, AVG(standard_qty) std_avg, AVG(poster_qty) pos_avg, AVG(glossy_qty) gloss_avg FROM accounts a JOIN orders o ON a.id = o.account_id GROUP BY 1), t2 AS (SELECT MAX(std_avg) max_std_avg, MAX(pos_avg) max_pos_avg , MAX(gloss_avg) max_gloss_avg FROM t1) SELECT std_id , max_std_avg, pos_id , max_pos_avg, glos_id , max_gloss_avg FROM(SELECT (SELECT id std_id FROM t1,t2 WHERE std_avg = max_std_avg), (SELECT id pos_id FROM t1,t2 WHERE pos_avg = max_pos_avg), (SELECT id glos_id FROM t1,t2 WHERE gloss_avg =max_gloss_avg) )foo ,t1,t2
結果:
std_id | max_std_avg| pos_id | max_pos_avg | glos_id | max_gloss_avg ----------------------------------------------------------------------- 1341 | 1891.7777 | 4251 | 2184.4615 | 4211 | 523.258 1341 | 1891.7777 | 4251 | 2184.4615 | 4211 | 523.258 ' ' ' ' ' 1341 | 1891.7777 | 4251 | 2184.4615 | 4211 | 523.258 (350 ROWS)
但是,輸出應該只有 1 個單行:
std_id | max_std_avg| pos_id | max_pos_avg | glos_id | max_gloss_avg ----------------------------------------------------------------------- 1341 | 1891.7777 | 4251 | 2184.4615 | 4211 | 523.258
如果有人能解釋為什麼,我將不勝感激?謝謝。
在最後一個外部查詢中,您
foo
與t1
and交叉連接t2
,而您只需要(並使用)來自foo
and的列t2
。所以刪除
t1
連接:WITH ... SELECT FROM ( ... ) foo, t2 ;
整個外部查詢可以進一步簡化,因為在三個子查詢加上主查詢中,您實際上並不需要
t2
使用四次。您可以使用一次,仍然可以加入t1
三次:WITH t1 AS ..., t2 AS ... SELECT std.id AS std_id, t2.max_std_avg, pos.id AS pos_id, t2.max_pos_avg, gloss.id AS gloss_id, t2.max_gloss_avg FROM t2 JOIN t1 AS std ON std .std_avg = t2.max_std_avg JOIN t1 AS pos ON pos .pos_avg = t2.max_pos_avg JOIN t1 AS gloss ON gloss.gloss_avg = t2.max_gloss_avg ;
另一種獲得相同結果但格式略有不同(3 行而不是 1 行)的方法是根本不使用連接,而是使用更多視窗函式。您還可以:
- 將兩個 CTE 合二為一。
accounts
從第一個 CTE中刪除。如果有FOREIGN KEY
fromorders
toaccounts
,結果將是相同的。新查詢:
WITH t1 AS (SELECT account_id, AVG(standard_qty) AS std_avg, AVG(poster_qty) AS pos_avg, AVG(glossy_qty) AS gloss_avg, MAX(AVG(standard_qty)) OVER () AS max_std_avg, MAX(AVG(poster_qty)) OVER () AS max_pos_avg , MAX(AVG(glossy_qty)) OVER () AS max_gloss_avg FROM orders o GROUP BY account_id) SELECT t1.*, CASE WHEN std_avg = max_std_avg THEN 'max_std_avg' ELSE NULL END AS std_result, CASE WHEN pos_avg = max_pos_avg THEN 'max_pos_avg' ELSE NULL END AS pos_result, CASE WHEN gloss_avg = max_gloss_avg THEN 'max_gloss_avg' ELSE NULL END AS gloss_result FROM t1 WHERE std_avg = max_std_avg OR pos_avg = max_pos_avg OR gloss_avg = max_gloss_avg ;