【问题标题】:subquery sum and newest record by different type不同类型的子查询总和和最新记录
【发布时间】:2022-12-08 01:37:38
【问题描述】:
table employee {
    id,
    name
}

table payment_record {
   id,
   type, // 1 is salary, 2-4 is bonus 
   employee_id,
   date_paid,
   amount
}

我想从某个日期查询员工的新薪水和总和(奖金)。 就像我的付款一样

id, type, employee_id, date_paid, amount
1      1            1  2022-10-01   5000
2      2            1  2022-10-01   1000
3      3            1  2022-10-01   1000     
4      1            1  2022-11-01   3000
5      1            2  2022-10-01   1000
6      1            2  2022-11-01   2000
7      2            2  2022-11-01   3000

查询日期 ['2022-10-01', '2022-11-01'] 给我看看

employee_id,  employee_name,  newest_salary, sum(bonus)
1             Jeff            3000           2000
2             Alex            2500           3000

其中 jeff 的新薪水是 3000,因为有 2 type = 1(salary) 记录 5000 和 3000,最新的是 3000。

杰夫的奖金总额是 1000(类型 2)+ 1000(类型 3)= 2000

我尝试的当前 sql 就像

select e.employee_id, employee.name, e.newest_salary, e.bonus from 
(select payment_record.employee_id, SUM(case when type in ('2', '3', '4') then amount end) as bonus, Max(case when type = '1' then amount end) as newest_salary from payment_record 
where date_paid in ('2022-10-01',  '2022-11-01')
group by employee_id) as e
join employee on employee.id = e.employee_id
order by employee_id

快完成了,但是 newest_salary 的规则不正确,我只是得到最大值,尽管通常最大值是最新记录。

【问题讨论】:

  • 你使用什么类型的数据库?
  • 我正在使用 postgresql

标签: sql


【解决方案1】:

我认为 Postgres 足够接近我在 sql-server 中测试的这个解决方案,但它至少应该足够接近以翻译

我的方法是将所需范围内的付款分成薪水与奖金,然后对奖金求和,但使用分区行号来确定所需日期范围内每位员工的最新薪水支付,并将该薪水加入奖金总额。请注意,我使用了 LEFT JOIN,因为员工可能得不到奖金。

DECLARE @StartDate DATE = '2022-10-01';
DECLARE @EndDate   DATE = '2022-11-01';

with cteSample as ( --BEGIN sample data
    SELECT * FROM ( VALUES 
        (1, 1, 1, CONVERT(DATE,'2022-10-01'), 5000)
        , (2, 2, 1, '2022-10-01', 1000)
        , (3, 3, 1, '2022-10-01', 1000)
        , (4, 1, 1, '2022-11-01', 3000)
        , (5, 1, 2, '2022-10-01', 1000)
        , (6, 1, 2, '2022-11-01', 2000)
        , (7, 2, 2, '2022-11-01', 3000)
    ) as TabA(Pay_ID, Pay_Type, employee_id, date_paid, amount) 
) --END Sample data
, ctePayments as ( --Filter down to just the payments in the date range you are interested in
    SELECT Pay_ID, Pay_Type, employee_id, date_paid, amount
    FROM cteSample --Replace this with your real table of payments
    WHERE date_paid >= @StartDate AND date_paid <= @EndDate  
), cteSalary as ( --Identify salary payments in range and order them newest first
    SELECT employee_id, amount
        , ROW_NUMBER() over (PARTITION BY employee_id ORDER BY date_paid DESC) as Newness
    FROM ctePayments as S
    WHERE S.Pay_Type = 1
), cteBonus as ( --Identify bonus payments in range and sum them
    SELECT employee_id, SUM(amount) as BonusPaid
    FROM ctePayments as S
    WHERE S.Pay_Type in (2,3,4)
    GROUP BY employee_id
)
SELECT S.employee_id, S.amount as SalaryNewest
    , COALESCE(B.BonusPaid, 0) as BonusTotal
FROM cteSalary as S --Join the salary list to the bonusa list
    LEFT OUTER JOIN cteBonus as B ON S.employee_id = B.employee_id 
WHERE S.Newness = 1 --Keep only the newest

结果:

employee_id SalaryNewest BonusTotal
1 3000 2000
2 2000 3000

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-15
    • 2020-10-23
    • 2021-06-01
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-03
    相关资源
    最近更新 更多