【问题标题】:Oracle SQL - Count only one of specified valueOracle SQL - 仅计算指定值之一
【发布时间】:2020-06-01 14:03:38
【问题描述】:

我确实希望有人可以帮助我。

我正在对我的列执行两个计数函数,这两个函数都由列具有特定文本的位置指定(参见下面的代码)。根据我的会议计数(WHERE EVENT_TYPE = 'meeting_start'),我发现这可以在同一个会议中多次弹出。我只需要对每个会议事件 id 计算一次,并且找不到这样做的方法。

select I.CRM_INSTANCE_NAME,
       C.CUSTOMER_NAME,
       U.USER_NAME,
       ltrim(TO_CHAR(U.CREATED_DATE ,'mm-yyyy'),'0') AS USER_ACTIVATION_DATE,
       ltrim(TO_CHAR(U.LAST_UPDATED_DATE ,'dd-mm-yyyy'),'0') AS LAST_ACTIVITY_DATE,
       COUNT(E.EVENT_TYPE) AS MEETING,
       COUNT(F.EVENT_TYPE) AS FINALISED

       FROM SBX_USERS U
        LEFT JOIN SBX_CUSTOMERS C on U.CUSTOMER_ID = C.CUSTOMER_ID
        LEFT JOIN SBX_CRM_INSTANCES I on C.CRM_INSTANCE_ID = I.CRM_INSTANCE_ID
        LEFT JOIN SBX_MEETING M on U.USER_ID = M.USER_ID
        LEFT JOIN SBX_EVENTS E ON SOURCE_ID  = M.MEETING_ID
        LEFT JOIN (SELECT * FROM SBX_EVENTS WHERE EVENT_TYPE = 'meeting_start' AND EVENT_CREATION_DATE >=add_months(sysdate, -12)) E on E.SOURCE_ID = M.MEETING_ID
        LEFT JOIN (SELECT * FROM SBX_EVENTS WHERE EVENT_TYPE = 'finalize'AND EVENT_CREATION_DATE >=add_months(sysdate, -12)) F on F.SOURCE_ID = M.MEETING_ID

where U.ENABLED_FLAG IN ('Y','E')

group by  I.CRM_INSTANCE_NAME, C.CUSTOMER_NAME, U.USER_NAME, ltrim(TO_CHAR(U.CREATED_DATE ,'mm-yyyy'),'0'), ltrim(TO_CHAR(U.LAST_UPDATED_DATE ,'dd-mm-yyyy'),'0')
order by  I.CRM_INSTANCE_NAME;

以上是我当时正在使用的代码,在此先感谢您的帮助。

问候

博士

【问题讨论】:

  • count(case when EVENT_TYPE = 'meeting_start' then 1 end)
  • 这涉及一个常见错误,人们想要一些连接,每个可能涉及不同的键,一些子查询,每个可能涉及连接和/或聚合,但他们错误地尝试完成所有连接然后全部聚合或聚合以前的聚合。在适当的行上编写单独的聚合和/或聚合一个案例语句选择行;加入一个独特的列集。有时 DISTINCT 聚合在非键连接后选择正确的值。 (对 2 个输入表中任一个的非键的连接可以为每个表的每个键提供多行。)

标签: sql oracle join group-by count


【解决方案1】:

你不需要来自 sbx_events 的两个额外的外部连接,你可以使用条件聚合来代替,例如类似:

select I.CRM_INSTANCE_NAME,
       C.CUSTOMER_NAME,
       U.USER_NAME,
       ltrim(TO_CHAR(U.CREATED_DATE ,'mm-yyyy'),'0') AS USER_ACTIVATION_DATE,
       ltrim(TO_CHAR(U.LAST_UPDATED_DATE ,'dd-mm-yyyy'),'0') AS LAST_ACTIVITY_DATE,
       COUNT(DISTINCT CASE WHEN E.EVENT_TYPE = 'meeting_start' AND eVENT_CREATION_DATE >=add_months(sysdate, -12) THEN 1 END) AS MEETING,
       COUNT(CASE WHEN E.EVENT_TYPE = 'finalize' AND eVENT_CREATION_DATE >=add_months(sysdate, -12) THEN 1 END) AS FINALISED
       FROM SBX_USERS U
        LEFT JOIN SBX_CUSTOMERS C on U.CUSTOMER_ID = C.CUSTOMER_ID
        LEFT JOIN SBX_CRM_INSTANCES I on C.CRM_INSTANCE_ID = I.CRM_INSTANCE_ID
        LEFT JOIN SBX_MEETING M on U.USER_ID = M.USER_ID
        LEFT JOIN SBX_EVENTS E ON SOURCE_ID  = M.MEETING_ID
where U.ENABLED_FLAG IN ('Y','E')
group by  I.CRM_INSTANCE_NAME, C.CUSTOMER_NAME, U.USER_NAME, ltrim(TO_CHAR(U.CREATED_DATE ,'mm-yyyy'),'0'), ltrim(TO_CHAR(U.LAST_UPDATED_DATE ,'dd-mm-yyyy'),'0')
order by  I.CRM_INSTANCE_NAME;

注意您有两个别名为 e 的表,所以我猜测您在计数中指的是哪一个。

此外,如果您只关心 meeting_start 和 finalize event_types,您可以将其添加为 sbx_events 表中的连接条件以及日期限制。

【讨论】:

    【解决方案2】:

    您需要在子选择中进行分组,即所谓的“表 E”,如下所示:

    select I.CRM_INSTANCE_NAME,
           C.CUSTOMER_NAME,
           U.USER_NAME,
           ltrim(TO_CHAR(U.CREATED_DATE ,'mm-yyyy'),'0') AS USER_ACTIVATION_DATE,
           ltrim(TO_CHAR(U.LAST_UPDATED_DATE ,'dd-mm-yyyy'),'0') AS LAST_ACTIVITY_DATE,
           COUNT(E.MEETING_NO) AS MEETING,
           COUNT(F.EVENT_TYPE) AS FINALISED
    
           FROM SBX_USERS U
            LEFT JOIN SBX_CUSTOMERS C on U.CUSTOMER_ID = C.CUSTOMER_ID
            LEFT JOIN SBX_CRM_INSTANCES I on C.CRM_INSTANCE_ID = I.CRM_INSTANCE_ID
            LEFT JOIN SBX_MEETING M on U.USER_ID = M.USER_ID
            LEFT JOIN SBX_EVENTS E ON SOURCE_ID  = M.MEETING_ID
            LEFT JOIN (SELECT EVENT_TYPE,SOURCE_ID,count(*) MEETING_NO FROM SBX_EVENTS WHERE EVENT_TYPE = 'meeting_start' AND EVENT_CREATION_DATE >=add_months(sysdate, -12) GROUP BY EVENT_TYPE,SOURCE_ID) E on E.SOURCE_ID = M.MEETING_ID
            LEFT JOIN (SELECT * FROM SBX_EVENTS WHERE EVENT_TYPE = 'finalize'AND EVENT_CREATION_DATE >=add_months(sysdate, -12)) F on F.SOURCE_ID = M.MEETING_ID
    
    where U.ENABLED_FLAG IN ('Y','E')
    
    group by  I.CRM_INSTANCE_NAME, C.CUSTOMER_NAME, U.USER_NAME, ltrim(TO_CHAR(U.CREATED_DATE ,'mm-yyyy'),'0'), ltrim(TO_CHAR(U.LAST_UPDATED_DATE ,'dd-mm-yyyy'),'0')
    order by  I.CRM_INSTANCE_NAME;
    

    【讨论】:

    • 您需要在子选择中进行分组,即所谓的“表 E”。我已经在上面发布了解决方案。我希望这有助于纠正您的查询。
    • 您应该将有关您的解决方案的所有相关信息放入答案本身。我已编辑您的答案以包含您评论中的相关信息 - 您现在应该删除您的评论。
    【解决方案3】:

    本质上,我认为你想要COUNT(DISTINCT ...)

    而且,您的查询不是有效的 SQL:您有两个名为 E 的别名:连接 sbx_events 的逻辑有问题。我怀疑您实际上希望在该表上进行一个联接(在日期上具有联接条件),并在 COUNT(DISTINCT) 中进行条件聚合。

    那就是:

    select 
        i.crm_instance_name,
        c.customer_name,
        u.user_name,
        ltrim(to_char(u.created_date ,'mm-yyyy'),'0') as user_activation_date,
        ltrim(to_char(u.last_updated_date ,'dd-mm-yyyy'),'0') as last_activity_date,
        count(distinct case when event_type = 'meeting_start'  then m.meeting_id end) as meeting,
        count(distinct case when event_type = 'finalize'  then m.meeting_id end) as finalized
    from sbx_users u
    left join sbx_customers c 
        on u.customer_id = c.customer_id
    left join sbx_crm_instances i 
        on c.crm_instance_id = i.crm_instance_id
    left join sbx_meeting m 
        on u.user_id = m.user_id
    left join sbx_events e 
        on source_id  = m.meeting_id
        and  e.event_creation_date >= add_months(sysdate, -12))
    where u.enabled_flag in ('y','e')
    group by  
        i.crm_instance_name, 
        c.customer_name, 
        u.user_name, 
        ltrim(to_char(u.created_date ,'mm-yyyy'),'0'), 
        ltrim(to_char(u.last_updated_date ,'dd-mm-yyyy'),'0')
    order by  i.crm_instance_name;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多