SQL中的高级比例计算

时间:2012-07-31 16:10:59

标签: sql-server sql-server-2008 tsql math

我试图确定DD(branch)与AA,BB,CC相关的比例,其中DD存在于员工,账户,水果的子集中。每位员工的pcnt加1(100%)。

将其分解,此计算必须满足以下条件:

  • 忽略没有DD的子集(员工,帐户,水果)
| EMPLOYEE | ACCOUNT |      FRUIT | BRANCH | PCNT |
---------------------------------------------------
|      123 |  Fruit1 |      Apple |     AA |  0.1 |
  • 忽略完全DD
  • 的子集(员工,帐户,水果)
| EMPLOYEE | ACCOUNT |      FRUIT | BRANCH | PCNT |
---------------------------------------------------
|      123 |  Fruit2 |      Apple |     DD | 0.05 |
  • 在子集(员工,帐户,水果)中按比例分配DD,AA,BB,CC

自:

| EMPLOYEE | ACCOUNT |      FRUIT | BRANCH | PCNT |
---------------------------------------------------
|      123 |  Fruit1 | Strawberry |     AA | 0.05 |
|      123 |  Fruit1 | Strawberry |     BB | 0.02 |
|      123 |  Fruit1 | Strawberry |     CC | 0.07 |
|      123 |  Fruit1 | Strawberry |     DD | 0.10 |

分为:

| EMPLOYEE | ACCOUNT |      FRUIT | BRANCH | PCNT |
---------------------------------------------------
|      123 |  Fruit1 | Strawberry |     AA | 0.09 |
|      123 |  Fruit1 | Strawberry |     BB | 0.03 |
|      123 |  Fruit1 | Strawberry |     CC | 0.12 |

上述子集比例的计算将是:

AA + {AA * [DD / (AA + BB + CC)]}

0.05 + {0.05 * [0.1 / (0.05 + 0.02 + 0.07)]} = 0.09
0.02 + {0.02 * [0.1 / (0.05 + 0.02 + 0.07)]} = 0.03
0.07 + {0.07 * [0.1 / (0.05 + 0.02 + 0.07)]} = 0.12
  • 在这些计算和条件之后,pcnt的总和应为1
  • 可能存在一些子集,其中不存在全部三个(AA,BB,CC)

表格结构

CREATE TABLE tbl (
  employee tinyint NOT NULL,
  account varchar(10) NOT NULL,
  fruit varchar(15) NOT NULL,
  branch char(2) NOT NULL,
  pcnt decimal(3,2) NULL
  PRIMARY KEY (employee, account, fruit, branch))

示例数据

INSERT INTO tbl (employee, account, fruit, branch, pcnt) VALUES 
(123, 'Fruit1', 'Apple', 'AA', '0.1'),
(123, 'Fruit1', 'Mango', 'DD', '0.02'),
(123, 'Fruit1', 'Mango', 'CC', '0.1'),
(123, 'Fruit1', 'Mango', 'BB', '0.02'),
(123, 'Fruit1', 'Mango', 'AA', '0.06'),
(123, 'Fruit1', 'Pineapple', 'DD', '0.01'),
(123, 'Fruit1', 'Pineapple', 'CC', '0.05'),
(123, 'Fruit1', 'Pineapple', 'BB', '0.05'),
(123, 'Fruit1', 'Pineapple', 'AA', '0.05'),
(123, 'Fruit1', 'Strawberry', 'DD', '0.10'),
(123, 'Fruit1', 'Strawberry', 'CC', '0.07'),
(123, 'Fruit1', 'Strawberry', 'BB', '0.02'),
(123, 'Fruit1', 'Strawberry', 'AA', '0.05'),
(123, 'Fruit2', 'Apple', 'DD', '0.05'),
(123, 'Fruit2', 'Mango', 'DD', '0.01'),
(123, 'Fruit2', 'Mango', 'CC', '0.02'),
(123, 'Fruit2', 'Mango', 'BB', '0.01'),
(123, 'Fruit2', 'Mango', 'AA', '0.01'),
(123, 'Fruit2', 'Pineapple', 'DD', '0.02'),
(123, 'Fruit2', 'Pineapple', 'CC', '0.03'),
(123, 'Fruit2', 'Pineapple', 'BB', '0.02'),
(123, 'Fruit2', 'Pineapple', 'AA', '0.02'),
(123, 'Fruit2', 'Strawberry', 'DD', '0.01'),
(123, 'Fruit2', 'Strawberry', 'CC', '0.05'),
(123, 'Fruit2', 'Strawberry', 'AA', '0.05')

我尝试了什么

SELECT b.*, 
    CASE WHEN (b.Sum_AA + b.Sum_BB + b.Sum_CC) > 0 THEN 'hello'
    ELSE NULL
    END
FROM (
    SELECT a.*, 
        (SELECT SUM(pcnt) AS [pcnt] FROM dbo.tbl
            WHERE employee = a.employee AND account = a.account AND fruit = a.fruit
            AND branch = 'AA') AS [Sum_AA],
        (SELECT SUM(pcnt) AS [pcnt] FROM dbo.tbl
            WHERE employee = a.employee AND account = a.account AND fruit = a.fruit
            AND branch = 'BB') AS [Sum_BB],
        (SELECT SUM(pcnt) AS [pcnt] FROM dbo.tbl
            WHERE employee = a.employee AND account = a.account AND fruit = a.fruit
            AND branch = 'CC') AS [Sum_CC]
    FROM (
        SELECT employee, account, fruit, SUM(pcnt) AS [Sum_DD]
        FROM dbo.tbl
        WHERE employee = 123 AND branch = 'DD'
        GROUP BY employee, account, fruit) a) b

直到上面的查询,我将AA,BB,CC分组。但是,我不知道如何继续。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:1)

不确定这是否是你需要的,试试这个。

WITH ct1 AS
(        
    SELECT employee, account, fruit
        ,SUM(CASE WHEN branch = 'AA' THEN pcnt ELSE 0 END) AS AA    
        ,SUM(CASE WHEN branch = 'BB' THEN pcnt ELSE 0 END) AS BB    
        ,SUM(CASE WHEN branch = 'CC' THEN pcnt ELSE 0 END) AS CC
        ,SUM(CASE WHEN branch = 'DD' THEN pcnt ELSE 0 END) AS DD
    FROM tbl 
    GROUP BY  employee, account, fruit having SUM(CASE WHEN branch = 'DD' THEN 1 ELSE 0 END) >= 1       
)
SELECT t.*
    ,new_pcnt = t.pcnt + ROUND((t.pcnt * ( DD /(AA + BB + CC))),2)
FROM tbl t
INNER JOIN ct1 
  ON t.employee = ct1.employee
  AND t.account = ct1.account
  AND t.fruit = ct1.fruit
WHERE t.branch <> 'DD'