SQL查询 - 如何检查结果是否优先

时间:2017-10-25 17:29:16

标签: sql postgresql

我在PostgreSQL中的查询显示了一段时间内的会议:start_date和:end_date。

问题在于“ktore”列,它表明会议是第一次。我使用“内部联接”来添加子查询,该子查询在公司中计算我的会议,如果 count> 1 ,然后写“next”,否则 - “first”。但它仅在上次会议日期显示正确的结果。让我举个例子:

在Company1有两次会议 - 2017-09-02会议1和2017-09-05会议2。

如果我选择:开始日期到2017-09-01和:end_date 到2017-09-06,那么我的查询显示:

id   company_name  audit_date  nip      ktore
...
234  Company1      2017-09-02  1234567  NEXT
...
287  Company1      2017-09-05  1234567  NEXT

但我想要这个:

id   company_name  audit_date  nip      ktore
...
234  Company1      2017-09-02  1234567  FIRST
...
287  Company1      2017-09-05  1234567  NEXT

那么我应该在查询中做些什么呢?

select a.id, a.company_name, to_char(a.audit_date,'YYYY-MM-DD hh:mi') audit_date, companys.nip, 
    case
        when b.costam > 1 then 'NEXT'
        else 'FIRST'
    end ktore
from companys, meetings a
    inner join (select company_id, count(1) costam from meetings where status !='CANCELED' and status !='SUSPENDED' 
        and to_char(audit_dc,'YYYY-MM-DD')<= :end_date group by company_id) b on a.company_id = b.company_id
where to_char(a.audit_date,'YYYY-MM-DD')>= :start_date 
and to_char(a.audit_date,'YYYY-MM-DD')<= :end_date and companys.id = a.company_id

我认为写一些类似“如果公司存在与早期日期会议,然后”NEXT“,否则”FIRST“会很好,但我不知道代码是如何做的。

提前谢谢你, Mateusz

2 个答案:

答案 0 :(得分:1)

尝试以下查询即可。我的逻辑是,从子查询中我最少使用audit_date,然后与主表审核日期进行比较,如果匹配,那么它将给出第一个其他NEXT,如果有一个companyId有3个不同的日期,那么它将为最小日期提供FIRST和剩下的日期

select a.id, a.company_name, to_char(a.audit_date,'YYYY-MM-DD hh:mi') audit_date, companys.nip, 
    case
        when b.costam >1 and min_audit_date=a.audit_date then 'FIRST'
        else 'NEXT'
    end ktore
from companys, meetings a
    inner join (select company_id, count(1) costam,min(audit_date) min_audit_date,max(audit_date) max_audit_date from meetings where status !='CANCELED' and status !='SUSPENDED' 
        and to_char(audit_dc,'YYYY-MM-DD')<= :end_date group by company_id) b on a.company_id = b.company_id
where to_char(a.audit_date,'YYYY-MM-DD')>= :start_date 
and to_char(a.audit_date,'YYYY-MM-DD')<= :end_date and companys.id = a.company_id

如果你的逻辑与我上面所做的相反,你可以改变逻辑  max_audit_date

答案 1 :(得分:0)

您正在做的事情会起作用,但更惯用的做法是使用Windowing Functions之类的内容,可能使用ROW_NUMBER()

SELECT Meetings.id, Meetings.company_name, 
       TO_CHAR(Meetings.audit_date, 'YYYY-MM-DD hh:mi') AS audit_date, 
       Companys.nip, 
       CASE WHEN ROW_NUMBER() OVER(PARTITION BY Meetings.company_id 
                                   ORDER BY Meetings.audit_date) = 1 
            THEN 'FIRST'
            ELSE 'NEXT'
       END AS ktore
FROM Meetings
JOIN Companys
  ON Companys.id = Meetings.company_id
WHERE Meetings.status NOT IN ('CANCELED', 'SUSPENDED')
      AND Meetings.audit_date >= TIMESTAMP :startDate
      AND Meetings.audit_date < TIMESTAMP :endDate
ORDER BY Meetings.company_id, Meetings.audit_date          

您会注意到您的查询中发生了许多变化。我还有其他一些想法。

  • Meetings.company_name - 我很难相信该列位于该表中,它可能更应该是Companys.company_name
  • 它是Companies,但是关于表名是否应该是单数而不是复数的争论很多。
  • 您的原始查询会计算某个点之前的所有会议,无论查询窗口如何,但是我当前的版本会在窗口中的第一次会议中返回'FIRST',这可能不是同一回事。目前还不清楚你真正想要的是什么。
  • 日期和时间always query them with an exclusive upper-bound。它简单易行。另外,查询的原始版本会忽略索引,并会使查询运行得更慢。
  • 此外,对于日期时间,您必须非常小心时区。不过,目前还不清楚这是否值得关注。