【问题标题】:Postgresql group by for multiple linesPostgresql group by 多行
【发布时间】:2019-03-10 14:28:07
【问题描述】:

我有这张表名为hr_holidays_by_calendar。我只想过滤掉同一员工在同一天有两次休假的行。

hr_holidays_by_calendar:

我试过的查询:
没办法解决这个问题。

select hol1.employee_id, hol1.leave_date, hol1.no_of_days, hol1.leave_state
from hr_holidays_by_calendar hol1
inner join
    (select employee_id, leave_date 
    from hr_holidays_by_calendar hol1
    group by employee_id, leave_date 
    having count(*)>1)sub
on hol1.employee_id=sub.employee_id and hol1.leave_date=sub.leave_date
where hol1.leave_state != 'refuse'
order by hol1.employee_id, hol1.leave_date

【问题讨论】:

  • 如果这些重复行中的天数不同怎么办?
  • where h.leave_state != 'refuse'在外层查询中的作用是什么?您可能需要在内部查询中进行过滤 - 取决于您未公开的要求。
  • 请记住,实际的表定义(CREATE TABLE ... 脚​​本)最有助于阐明您的设置。而且我们更喜欢文本作为 data 而不是屏幕截图。无法从屏幕截图中复制/粘贴...

标签: sql postgresql duplicates postgresql-9.3


【解决方案1】:

这将返回存在重复的所有行

SELECT employee_id, leave_date, no_of_days, leave_state
FROM   hr_holidays_by_calendar h
WHERE  EXISTS (
   SELECT -- select list can be empty for EXISTS
   FROM   hr_holidays_by_calendar
   WHERE  employee_id = h.employee_id
   AND    leave_date = h.leave_date
   AND    leave_state <> 'refuse'
   AND    ctid <> h.ctid
   )
AND    leave_state <> 'refuse'
ORDER  BY employee_id, leave_date;

目前还不清楚leave_state &lt;&gt; 'refuse' 应该适用于何处。您必须定义要求。我的示例完全排除了带有leave_state = 'refuse'(以及带有leave_state IS NULL!)的行。

ctid 是您未公开的(未定义?)主键的替代品。

相关:

【讨论】:

  • 非常感谢 Erwin Brandstetter ......这就是我需要做的。我真的很抱歉缺乏信息。再次感谢您的清晰指南
【解决方案2】:

我假设你只需要颠倒你的逻辑。你可以使用NOT EXISTS:

select h1.employee_id, h1.leave_date, h1.no_of_days, h1.leave_state
from hr_holidays_by_calendar h1
where 
  h1.leave_state <> 'refuse'
  and not exists (
    select 1
    from hr_holidays_by_calendar h2
    where 
      h1.employee_id = h2.employee_id
      and h1.leave_date = h2.leave_date
      group by employee_id, leave_date
      having count(*) > 1
  )

这将丢弃每对(员工,日期)超过一行的(在同一天离开)。

我没有考虑天数,因为无论如何这似乎是错误的 - 您不能在同一天两次请假,持续不同的天数。如果您的应用程序允许,请考虑应用其他逻辑。另外,你不应该让这些记录首先出现在表格中:-)

【讨论】:

    【解决方案3】:

    我相信简单地使用 GROUP BY 就可以为您完成这项工作

    select hol1.employee_id, hol1.leave_date, max(hol1.no_of_days)
    from hr_holidays_by_calendar hol1
    where hol1.leave_state != 'refuse'
    group by hol1.employee_id, hol1.leave_date
    

    不清楚如果两行有不同的no_of_days会发生什么。

    【讨论】:

      【解决方案4】:

      如果你想要完整的行,一种方法是使用窗口函数:

      select hc.*
      from (select hc.*, count(*) over (partition by employee_id, leave_date) as cnt
            from hr_holidays_by_calendar hc
           ) hc
      where cnt >= 2;
      

      如果您只需要员工 ID 和日期,则适合聚合。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-30
        • 1970-01-01
        • 2020-02-08
        • 1970-01-01
        • 1970-01-01
        • 2017-10-28
        • 2010-12-18
        • 1970-01-01
        相关资源
        最近更新 更多