CTE 和子查询的非常奇怪的结果

1 cte subquery

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
Run Code Online (Sandbox Code Playgroud)

结果:

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)
Run Code Online (Sandbox Code Playgroud)

但是,输出应该只有 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
Run Code Online (Sandbox Code Playgroud)

如果有人能解释原因,我将不胜感激?谢谢。

ype*_*eᵀᴹ 5

在最后一个外部查询中,您foo使用t1and交叉连接t2,而您只需要(和使用)来自fooand 的列t2

所以删除t1连接:

WITH 
    ...
SELECT
FROM (
     ...
     ) foo, t2 ; 
Run Code Online (Sandbox Code Playgroud)

整个外部查询可以进一步简化,因为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
;
Run Code Online (Sandbox Code Playgroud)

另一种获得相同结果但格式略有不同(3 行而不是 1 行)的方法是根本不使用连接,而是使用更多的窗口函数。你也可以:

  • 将两个 CTE 合二为一。
  • accounts从第一个 CTE 中删除。如果有FOREIGN KEYfrom ordersto accounts,结果将是相同的。

新查询:

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 ;
Run Code Online (Sandbox Code Playgroud)