簡體   English   中英

SQL Server查詢:如何使用左外部聯接

[英]SQL Server query : how to use left outer join

我有這個SQL查詢:

SELECT 
    COALESCE(a.U, '') AS U, 
    COALESCE(a.N, '') AS N,
    COALESCE (a.J, '')AS J,
    DATENAME(mm, a.P) AS Month,
    DATENAME(yyyy, a.P) AS Year,
    COALESCE(SUM(a.T), 0)  AS Total,
    COALESCE(SUM(b.Pa), 0) AS Cr,
    COALESCE(SUM(a.T), 0) - COALESCE(SUM(b.Pa), 0) AS TPa    
FROM 
    t1 AS a
LEFT OUTER JOIN
    (SELECT 
         U, N, SUM(Cr)
     FROM
         t2 
     WHERE 
         U IS NOT NUll AND N IS NOT NULL
    GROUP BY 
         U, N) AS b ON a.U = b.U AND a.N = b.N
WHERE 
    a.L IS NOT NULL
GROUP BY 
    a.U, a.N, a.J,
    DATENAME(mm, a.P), DATENAME(yyyy, a.P)
ORDER BY 
    Month, Year DESC 

該查詢將產生以下輸出:

+----+-------+---+--------+-------+---------+------+--------+
| U  | N     | J |  Month | Year  | Total   |  Cr  |  Tpa   |
+----+-------+---+--------+-------+---------+------+--------+
| 2B | Mark  | a | April  | 2016  | 1500    |  0   | 1500   |
| 2D | Jhon  | b | April  | 2016  | 100     | 4300 | -4200  |
| 2D | Jhon  | a | April  | 2016  | 2000    | 4300 | -2300  |
| 3A | Van   | a | April  | 2016  | 1500    | 7000 | -5500  |
| 2D | Jhon  | a | May    | 2016  | 500     | 4300 | -3800  |
| 3A | Van   | a | May    | 2016  | 1200    | 7000 | -5800  |
+----+-------+---+--------+-------+---------+------+--------+

如果我想生成此輸出,如何進行SQL查詢:

+----+-------+---+--------+-------+---------+------+--------+-------+
| U  | N     | J |  Month | Year  | Total   |  Cr  |  Tpa   | R     |
+----+-------+---+--------+-------+---------+------+--------+-------+
| 2B | Mark  | a | April  | 2016  | 1500    |  0   |  0     | 1500  |
| 2D | Jhon  | b | April  | 2016  | 100     | 4300 | -4200  |  0    |
| 2D | Jhon  | a | April  | 2016  | 2000    | 4200 | -2200  |  0    |
| 3A | Van   | a | April  | 2016  | 1500    | 7000 | -5500  |  0    |
| 2D | Jhon  | a | May    | 2016  | 500     | 2200 | -1700  | -1700 |
| 3A | Van   | a | May    | 2016  | 1200    | 5500 | -4300  | -4300 |
+----+-------+---+--------+-------+---------+------+--------+-------+

首先,(從表行1,2,4集中)從查詢行12-16獲得c列值。 然后在表第3行中(表第3行的U和表第2行的N相同),從絕對值獲得c的值:

來自Total(第2行)-Cr(第2行)。 換句話說,列C是從以前具有U和相同N(由U和N分組)的ABS(Tpa)獲得的。

C柱是從以前具有U和相同N(由U和N分組)的ABS(Tpa)獲得的。

Tpa列中的值是從Total-Cr列中獲得的。 如果Total-Cr> 0,則Tpa = 0且R = Total-Cr,但如果Total-Cr <= 0,則Tpa = Total-Cr且列R = 0。

表第5和6行中的R值是Total-Cr的結果。 如果表行是表中的最后一行(按U和N分組),則會發生這種情況。

根據我的理解,可以使用諸如LAG / LEAD之類的分析功能並通過SUM(...)over(PARTITION BY ... ORDER BY ...)來計算運行總計,輕松解決此類任務。

不幸的是,這些選項僅從SQL Server 2012開始可用。因此,我嘗試進行更復雜的查詢,但該查詢甚至應在較早版本上運行(於2008年嘗試)。

這是查詢。

我在公用表表達式(CTE)t1,t2中生成了值。

T3主要模仿您的查詢。 只需添加row_number()即可唯一地標識組中的行,還可以查找組中的最后一條記錄。

最后,t4有新的計算。

with 
t1 as 
(
    select '2B' as U, 'Mark' as N, 'a' as J, '2016-04-01' as P, 1500 as T, 1 as L union all 
    select '2D' as U, 'Jhon' as N, 'b' as J, '2016-04-01' as P, 100 as T, 1 as L union all 
    select '2D' as U, 'Jhon' as N, 'a' as J, '2016-04-04' as P, 2000 as T, 1 as L union all 
    select '2D' as U, 'Jhon' as N, 'a' as J, '2016-05-05' as P, 500 as T, 1 as L union all 
    select '3A' as U, 'Van' as N, 'a' as J, '2016-04-05' as P, 1500 as T, 1 as L union all 
    select '3A' as U, 'Van' as N, 'a' as J, '2016-05-05' as P, 1200 as T, 1 as L
),

t2 as 
(
    select '2B' as U,'Mark' as N, 0 as Cr union all
    select '2D' as U,'Jhon' as N, 4300 as Cr union all
    select '3A' as U,'Van' as N, 7000 as Cr
),

t3 as 
(
    SELECT 
        COALESCE(a.U, '') AS U, 
        COALESCE(a.N, '') AS N,
        COALESCE (a.J, '')AS J,
        DATENAME(mm, a.P) AS Month,
        DATENAME(yyyy, a.P) AS Year,
        COALESCE(SUM(a.T), 0)  AS Total,
        COALESCE(SUM(b.Pa), 0) AS Cr,
        --COALESCE(SUM(a.T), 0) - COALESCE(SUM(b.Pa), 0) AS TPa, 
        row_number() over (partition by a.U, a.N order by J desc, DATENAME(mm, a.P)) rn,
        row_number() over (partition by a.U, a.N order by J , DATENAME(mm, a.P) desc) rn_last
    FROM 
        t1 AS a
    LEFT OUTER JOIN
        (SELECT 
             U, N, SUM(Cr) as Pa
         FROM
             t2 
         WHERE 
             U IS NOT NUll AND N IS NOT NULL
        GROUP BY 
             U, N) AS b ON a.U = b.U AND a.N = b.N
    WHERE 
        a.L IS NOT NULL
    GROUP BY 
        a.U, a.N, a.J,
        DATENAME(mm, a.P), DATENAME(yyyy, a.P)
)

,t4 as (
    select cte1.*
    ,sum(cte2.Total) Cum_Total -- running total
    ,cte1.Cr - sum(cte2.Total) as Cr_Next
    from t3 cte1
    inner join t3 cte2 on cte1.U = cte2.U and cte1.N = cte2.N and cte1.rn >= cte2.rn
    group by 
    cte1.U, cte1.N, cte1.J, cte1.Month, cte1.Year, cte1.Total, cte1.Cr, cte1.rn, cte1.rn_last
) 

select U,N,J,Month,Year,Total,Cr_New as Cr,
case when Total - Cr_New > 0 then 0 else Total - Cr_New end as Tpa,
case when rn_last = 1 then Total - Cr_New else 0 end R
from
(
    select cte1.* 
    , case when cte1.rn =1 then cte1.Cr else cte2.Cr_Next end as Cr_New
    from t4 as cte1
    left join t4 cte2 on cte1.U = cte2.U and cte1.N = cte2.N and cte1.rn = cte2.rn +1
) t
order by 1,2,3 desc

它產生所需的准確結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM