【问题标题】:SQL query involving partial group with condition?涉及带条件的部分组的 SQL 查询?
【发布时间】:2020-06-08 08:08:18
【问题描述】:

以下是我无法理解正确方法的 SQL 查询问题:

数据库表:

Employee: emp_id, emp_name
Credit: credit_id, emp_id, credit_date, credit_amount
debit: debit_id, emp_id, debit_date, debit_amount

在这里,每个人可以有多种收入和支出。

查询要求:每天结束时,每个员工都会有一些资产('贷到现在' - '借到现在')。我们需要根据最大资产以及他们拥有该最大资产的日期来找出前五名员工。

我已经尝试了以下查询,但似乎我遗漏了一些东西:

select Credit.emp_id, Credit.date, (Credit.income_amount - Debit.credit_amount) from 
(select emp_id, sum(amount) as credit_amount 
from credit) Credit
LEFT JOIN LATERAL (
     select emp_id, sum(amount) as debit_amount
     from debits
     where debits.emp_id = Credit.emp_id and Credit.date >= debits.date
     group by debits.emp_id
    ) Debit
ON true

【问题讨论】:

  • 听起来您需要一个函数来运行计算、存储结果,然后将它们相互比较以找到五名员工。你能分享你尝试过的东西吗?请看minimal-reproducible-example

标签: mysql sql database postgresql


【解决方案1】:

Group by 和 sum 允许您将每个人的总学分放入 1 条记录中。您可以在子查询中执行类似的操作来减去借项。

Select top 5 emp_id, credit_date, (sum(credit_amount) - 
(select sum(debit_amount) from debit d 
where c.emp_id = d.emp_id and c.credit_date = d.debit_date)
) as total
from Credit c group by emp_id, credit_date order by total

【讨论】:

  • 请看how-to-answer,不解释就回答是没有用的。
  • 我们必须计算他在任何一天的最大资产..即在每个 credit_date -(他的 total_credits_till_that_day - total_debits_till_that_day = total_balance_on_that_day)。我们必须每天计算这个然后给出答案
【解决方案2】:

在这里,我打破了查询以使其更具可读性。

首先,我们需要获取贷方和借方的日级别的总金额,以便我们可以使用相同的emp_id加入日级别的贷方和借方表。

with 
credit as(
    select emp_id,credit_date date,sum(credit_amount) as amount
    from credit  
    group by 1,2),

debit as(
    select emp_id,debit_date,sum(debit_amount) as amount
    from expenses 
    group by 1,2),

现在我们需要完全外连接“贷方”和“借方”子查询

payments as (
    select distinct
    case when c.emp_id is null then d.person_id else c.emp_id  end as emp_id ,
    case when c.emp_id is null then d.date else c.date end as date,
    case when c.emp_id is null then 0 else i.amount end as credit ,
    case when d.emp_id is null then 0 else d.amount end as debit 
    from credit c
    full outer join debit d on d.emp_id=c.emp_id and d.date=c.date
    ),

现在我们将按天计算贷方、借方和总余额的累计金额,如下所示。

total_balance as(
    SELECT emp_id, date, 
    sum(credit) OVER (PARTITION BY emp_id ORDER BY date asc) AS total_credit,
    sum(debit) OVER (PARTITION BY emp_id ORDER BY date asc) AS total_debit,
    (sum(income) OVER (PARTITION BY person_id ORDER BY date asc) - 
    sum(expense) OVER (PARTITION BY person_id ORDER BY date asc)) as total_balance
    FROM group_payment
    ORDER BY person_id, date),

现在我们需要使用 rank() 函数根据总余额 (desc) 为 emp_id 分配排名(即,rank=1 将分配给特定 emp_id 一天中最大的总余额)。查询如下所示。

ranks as (select emp_id,date,total_balance,
rank() over (partition by emp_id order by total_balance desc) as rank
from total_balance ),

现在选择 rank=1 的行(即,对于 emp_id,一天中 total_balance 的 MAX 以及它为 MAX 的日期)。 按 total_balance 降序排序并选择前 5 行

emp_order as (select emp_id,date,total_balance 
from ranks
where rank=1
order by 3 desc
limit 5)

现在从员工表中选择名称。

select emp_id,name, date, total_balance as balance
from emp_order eo
join Employee e on e.emp_id = eo.emp_id
order by 4 desc

【讨论】:

    猜你喜欢
    • 2016-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 2015-12-02
    相关资源
    最近更新 更多