2016-03-01 48 views
0

這個查詢以這種方式工作得很好:如何避免DRY PostgreSQL中有嵌套查詢

SELECT DISTINCT inv.move_id, 
       inv.client_id, 
       inv.reference, 
       inv.date_inv, 
       inv.amount, 
       inv.state, 
       inv.client_type, 
       inv.agent_id, 
       (
         SELECT SUM(nc.amount) AS total 
         FROM invoice nc 
         WHERE nc.journal = 15 
         AND nc.ref_move = inv.move_id 
         AND nc.state = inv.state 
       ) AS credit, ( 
         SELECT SUM(ip.amount) 
         FROM inv_payment ip 
         WHERE inv.reference = ip.reference 
       ) AS paid, 
       (inv.amount) - (
        coalesce((
        SELECT SUM(nc.amount) AS total 
        FROM invoice nc 
        WHERE nc.journal = 15 
        AND nc.ref_move = inv.move_id 
        AND nc.state = inv.state 
       ), 0) + coalesce((
        SELECT SUM(ip.amount) 
        FROM inv_payment ip 
        WHERE inv.reference = ip.reference 
       ), 0) 
       ) AS outstanding 
FROM invoice inv 
    INNER JOIN inv_move im ON im.id = inv.move_id 
    INNER JOIN client cl ON cl.id = inv.client_id 
WHERE inv.agent_id = '%' 
    AND inv.date_inv 
    BETWEEN '%' AND '%' 
    AND inv.state = 'open' 
ORDER BY inv.agent_id 

我想晾乾這樣做:

SELECT DISTINCT inv.move_id, 
        inv.client_id, 
        inv.reference, 
        inv.date_inv, 
        inv.amount, 
        inv.state, 
        inv.client_type, 
        inv.agent_id, 
        (
         SELECT SUM(nc.amount) AS total 
         FROM invoice nc 
         WHERE nc.journal = 15 
         AND nc.ref_move = inv.move_id 
         AND nc.state = inv.state 
        ) AS credit, ( 
         SELECT SUM(ip.amount) 
         FROM inv_payment ip 
         WHERE inv.reference = ip.reference 
        ) AS paid, 
        (inv.amount) - (
         coalesce((credit), 0) + coalesce((paid), 0) 
        ) AS outstanding 
    FROM invoice inv 
     INNER JOIN inv_move im ON im.id = inv.move_id 
     INNER JOIN client cl ON cl.id = inv.client_id 
    WHERE inv.agent_id = '%' 
     AND inv.date_inv 
     BETWEEN '%' AND '%' 
     AND inv.state = 'open' 
    ORDER BY inv.agent_id 

但我發現了一個這樣的錯誤。 因爲我想將別名列用於其他列中的操作值。 我該怎麼辦? 我正在嘗試使用WITH PostgreSQL語句,但我無法以這種方式找到更好的解決方案。在FROM

+1

無關,但使用DISTINCT這樣是不好的數據質量。當從查詢中添加或刪除列時,會導致混淆/令人驚訝的結果。它也掩蓋了邏輯問題。如果您獲得了多個不需要的行,請查看您的連接並找出它們來自哪裏。通常這個問題是一個連接標準不夠嚴格。 –

回答

3

CANT使用在同一水平上計算的領域。

SELECT 1 + 2 as three, three * 2 as six 
         ^^^^^ 
         undefined 

因此,要麼創建子查詢。

SELECT three*2 as six 
FROM (SELECT 1 + 2 as three 
     FROM table 
    ) T 

或您的示例使用JOIN

使用CTE:

WITH cte as (
    SELECT ref_move, state, SUM(nc.amount) AS total 
    FROM invoice nc 
    WHERE nc.journal = 15 
    GROUP BY ref_move, state 
) 
SELECT * 
FROM invoice i 
JOIN cte c 
    ON i.ref_move= c.ref_move 
AND i.state = c.state 
1

使用子查詢:

SELECT *, amount-credit-paid AS outstanding FROM (
    SELECT DISTINCT inv.move_id, 
      inv.client_id, 
      inv.reference, 
      inv.date_inv, 
      inv.amount, 
      inv.state, 
      inv.client_type, 
      inv.agent_id, 
      (
        SELECT SUM(nc.amount) AS total 
        FROM invoice nc 
        WHERE nc.journal = 15 
        AND nc.ref_move = inv.move_id 
        AND nc.state = inv.state 
      ) AS credit, ( 
        SELECT SUM(ip.amount) 
        FROM inv_payment ip 
        WHERE inv.reference = ip.reference 
      ) AS paid 
    FROM invoice inv ... 
) AS _;