2014-05-07 27 views
1

我是SQL Server新手/用於MySQL數據庫,我遇到了一個我從未遇到過的與MySQL有關的問題。我正在尋求將所有當前的保單編號,所屬公司/人員的名稱,保費總額,以及他們是否擁有我們稱之爲「設備細分」的覆蓋範圍。這很簡單,我遇到的問題是分組。我想只按一列分組,也就是一個不同的保單號碼,公司名稱,保費的總和(可能有幾個保費金額都是負值和正值,所以我想總結一下,看看真實總額是多少),以及設備故障的簡單Yes或No列。由T-SQL與MySQL組成(單列)

這裏是我運行查詢:

SELECT pol_num as policy_number, 
insd_name as insureds_name, 
SUM(amt) as 'total_premium', 
(SELECT 
    CASE 
     WHEN cvg_desc = 'Equipment Breakdown' 
      THEN 'Y' 
     ELSE 'N'  
    END) as 'equipment_breakdown' 
FROM bapu.dbo.fact_prem 
WHERE '2014-05-06' between d_pol_eff and d_pol_exp 
AND amt_type = 'Premium' 
AND amt_desc = 'Written Premium' 
GROUP BY pol_num 
ORDER BY policy_number 

我得到一個錯誤說我需要按insd_name和cvg_desc爲好,但我不希望如此,因爲它給了我重複的策略數字。

這裏是我所得到的一個例子,當我組的一切它告訴我:

policy_number insureds_name  total_premium  equipment_breakdown 

001    company a   0.00    n 
001    company a   25,000.00   n 
001    company a   -10,000.00   n 
002    company b   100.00    y 
002    company b   10,000.00   y 

這裏是我想要的結果的一個例子:

policy_number insureds_name  total_premium  equipment_breakdown 

001    company a   15,000.00   n 
002    company b   10,100.00   y 

基本上,我只是想根據保單號進行分組並將保費金額相加。以上是我如何在MySQL中實現這一點,我如何才能實現我在SQL Server中尋找的結果?

感謝

回答

0

你需要在你不想要分組的字段的聚合函數。一個簡單的使用方法是MAX,它適用於大多數類型;

SELECT pol_num as policy_number, 
MAX(insd_name) as insureds_name, 
SUM(amt) as 'total_premium', 
(SELECT 
    CASE 
     WHEN MAX(cvg_desc) = 'Equipment Breakdown' 
      THEN 'Y' 
     ELSE 'N'  
    END) as 'equipment_breakdown' 
FROM bapu.dbo.fact_prem 
WHERE '2014-05-06' between d_pol_eff and d_pol_exp 
AND amt_type = 'Premium' 
AND amt_desc = 'Written Premium' 
GROUP BY pol_num 
ORDER BY policy_number 

的SQL Server希望這樣做的原因是,它喜歡給確定性的答案,例如

column_a | column_b 
1  | 1 
1  | 2 

...只column_a分組將在MySQL給予1或2作爲一個答案column_b,而SQL Server希望你明確地告訴它要使用哪一個。

+0

@cory和約阿希姆伊薩克森,這些工作都, 非常感謝你。我瘋了嗎?從我記憶中來看,在MySQL中這些都不是必須的,你可以只用一列進行分組,而不用大驚小怪。 – user3365317

+0

@ user3365317是的,問題在於我的答案底部,MySQL可以給同一個查詢運行兩次不同的結果。 SQL Server具有更嚴格(和標準)的分組規則,每次都會返回相同的答案。 –

+0

@ user3365317你不一定瘋了,但MySQL在這方面只是明顯的錯誤。 – podiluska

0

我大概如下寫這篇文章 - 沒有測試

SELECT pol_num as policy_number, 
insd_name as insureds_name, 
SUM(amt) as total_premium 
CASE 
    WHEN cvg_desc = 'Equipment Breakdown' 
     THEN 'Y' 
    ELSE 'N'  
END as equipment_breakdown 
FROM bapu.dbo.fact_prem 
WHERE '2014-05-06' between d_pol_eff and d_pol_exp 
AND amt_type = 'Premium' 
AND amt_desc = 'Written Premium' 

GROUP BY 
pol_num, policy_number, 
CASE 
    WHEN cvg_desc = 'Equipment Breakdown' 
     THEN 'Y' 
    ELSE 'N'  
END 
ORDER BY policy_number 
1

MySQL不會要求被包含在GROUP BY子句中的所有非集合場,即使不這樣做可能產生意想不到的效果。 SQL Server需要這個,所以你不得不決定要如何處理多個insd_name值對於一個給定pol_num,您可以使用MAX()MIN(),或者如果值總是一樣的,只是將它們添加到您的GROUP BY

SELECT pol_num AS policy_number 
     , MAX(insd_name) AS insureds_name 
     , SUM(amt) AS 'total_premium' 
     , MAX(CASE WHEN cvg_desc = 'Equipment Breakdown' THEN 'Y' 
      ELSE 'N' 
     END) AS 'equipment_breakdown' 
FROM bapu.dbo.fact_prem 
WHERE '2014-05-06' BETWEEN d_pol_eff AND d_pol_exp 
     AND amt_type = 'Premium' 
     AND amt_desc = 'Written Premium' 
GROUP BY pol_num 
ORDER BY policy_number 

或者:

SELECT pol_num AS policy_number 
     , insd_name AS insureds_name 
     , SUM(amt) AS 'total_premium' 
     , CASE WHEN cvg_desc = 'Equipment Breakdown' THEN 'Y' 
      ELSE 'N' 
     END AS 'equipment_breakdown' 
FROM bapu.dbo.fact_prem 
WHERE '2014-05-06' BETWEEN d_pol_eff AND d_pol_exp 
     AND amt_type = 'Premium' 
     AND amt_desc = 'Written Premium' 
GROUP BY pol_num 
     , insd_name 
     , CASE WHEN cvg_desc = 'Equipment Breakdown' THEN 'Y' 
      ELSE 'N' 
     END 
ORDER BY policy_number 
1

它看起來像cvg_desc列大概是什麼搞亂你。您想根據CASE語句生成的YN進行分組,但SQL服務器按原始cvg_desc列進行分組。您可以通過在分組之前解決CASE聲明的方式來解決此問題。例如,將主查詢包裝在公用表格表達式(CTE)中,這有點像內聯視圖。然後用設備的故障列上premium減少到只有一個YN,從CTE後續查詢與您SUM聚合應該給你你想要的結果:

WITH Policies(policy_number, insureds_name, premium, equipment_breakdown) AS 
(
    SELECT 
     pol_num 
     ,insd_name 
     ,amt 
     ,(CASE WHEN cvg_desc = 'Equipment Breakdown' THEN 'Y' ELSE 'N' END) 
      AS 'equipment_breakdown' 
    FROM 
     bapu.dbo.fact_prem 
    WHERE 
     '2014-05-06' BETWEEN d_pol_eff AND d_pol_exp 
     AND 
     amt_type = 'Premium' 
     AND 
     amt_desc = 'Written Premium' 
) 
SELECT 
    policy_number 
    ,insureds_name 
    ,SUM(premium) AS total_premium 
    ,equipment_breakdown 
FROM 
    Policies 
GROUP BY 
    policy_number 
    ,insureds_name 
    ,equipment_breakdown 
+0

請注意,Gary的答案通過將'CASE'語句放在'GROUP BY'中是有效的,這是一個選項,但我更喜歡這種方式,因爲不需要重複維護。 –