2017-03-15 80 views
0

假設我有一個這樣的表:分配類別

CampaignId Category Strike 
    1   A   2 
    1   B   3 
    1   Others  5 
    2   A   4 
    2   B   2 
    3   C   1 
    3   C   4 
    4   A   1 
    4   B   1 
    4   C   1 
    4   D   1 
    4   Others  1 

然後,我會計算每個CategoryStrike百分比CampaignId這樣的:

SELECT CampaignId, Category, Strike, (SUM(Strike::FLOAT) OVER (PARTITION BY CampaignId)/SUM(Strike::FLOAT) OVER (PARTITION BY CampaignId, Category) * 100) AS PercentageOfStrikesByCategoryByCampaignId 
FROM myTable 

造成中間表如下:

CampaignId Category Strike PercentageOfStrikesByCategoryByCampaignId 
    1   A   2  20.0 
    1   B   3  30.0 
    1   Others  5  50.0 
    2   A   4  66.6 
    2   B   2  33.3 
    3   C   1  20.0 
    3   C   4  80.0 
    4   A   1  20.0 
    4   B   1  20.0 
    4   C   1  20.0 
    4   D   1  20.0 
    4   Others  1  20.0 

現在,我想根據上面計算的PercentageOfStrikesByCategoryByCampaignId分配一個最終標籤,說FinalCategoryFinalCategory的標準要點是:如果每個CampaignId中的其中一個類別爲'其他'ANDPercentageOfStrikesByCategoryByCampaignId >= 30.0,則該CampaignId組中的其餘行將標記爲'其他'。否則,我們將Category直接複製到FinalCategory。結果表應該如下所示:

CampaignId Category Strike PercentageOfStrikesByCategoryByCampaignId FinalCategory 
    1   A   2  20.0          Others 
    1   B   3  30.0          Others 
    1   Others  5  50.0          Others 
    2   A   4  66.6          A 
    2   B   2  33.3          B 
    3   C   1  20.0          C 
    3   C   4  80.0          C 
    4   A   1  20.0          A 
    4   B   1  20.0          B 
    4   C   1  20.0          C 
    4   D   1  20.0          D 
    4   Others  1  20.0          Others 

我該如何使用盡可能簡單的SQL查詢來實現這樣的事情?預先感謝您的幫助!

回答

1
SELECT CampaignId, Category, Strike, PercentageOfStrikesByCategoryByCampaignId, 
CASE WHEN Others_count > 0 AND 
    MAX(CASE WHEN Category='Others' THEN PercentageOfStrikesByCategoryByCampaignId END) OVER (PARTITION BY CampaignId) >= 30 THEN 'Others' 
ELSE Category END AS FinalCategory 
FROM (
SELECT CampaignId, Category, Strike, 
(SUM(Strike::FLOAT) OVER (PARTITION BY CampaignId) 
/SUM(Strike::FLOAT) OVER (PARTITION BY CampaignId, Category) * 100) AS PercentageOfStrikesByCategoryByCampaignId 
,SUM(CASE WHEN Category='Others' THEN 1 ELSE 0 END) OVER (PARTITION BY CampaignId) as Others_count 
FROM myTable 
) T 

添加到現有的查詢中

  • Others_Count爲與sum窗口函數每個CAMPAIGNID
  • 使用case的表達與計算Others_Count和max窗口功能,如果要檢查的行與Others類別具有> = 30的百分比,並將'其他'指定爲最終類別,否則按原樣使用該類別。
+0

太謝謝你了!這像一個魅力。由此,我學到了一招:使用'CASE WHEN'計數器的'SUM'作爲標誌。 :) – user1330974

1

讓我們先從你的查詢作爲CTE或子查詢:

WITH t as (
     SELECT CampaignId, Category, Strike, 
      (SUM(Strike::FLOAT) OVER (PARTITION BY CampaignId)/SUM(Strike::FLOAT) OVER (PARTITION BY CampaignId, Category) * 100) AS PercentageOfStrikesByCategoryByCampaignId 
     FROM myTable 
    ) 
select t.*, 
     (case when OthersFlag = 1 then 'Others' else category end) as FinalCategory 
from (select t.*, 
      sum(case when category = 'Others' and PercentageOfStrikesByCategoryByCampaignId > 30.0 then 1 else 0 end) over 
       (partition by campaignid) as OthersFlag 
     from t 
    ) t; 
+0

感謝您提供一個可讀性強(易於理解)的解決方案!我接受vkp的解決方案作爲答案,因爲他的發佈時間比你早,他的答案適用於Vertica(不僅僅是T-SQL)。 :) – user1330974

+0

@ user1330974。 。 。這不是T-SQL的答案,儘管它可以很容易地修改。這個答案和Vertica有什麼問題? –

+0

['WITH'](https://msdn.microsoft.com/en-us/library/ms175972.aspx)(或CTE)不是Vertica的一部分。謝謝你的幫助。 – user1330974