【问题标题】:Oracle SQL Group By a String Aggregated FieldOracle SQL 按字符串聚合字段分组
【发布时间】:2015-03-05 02:41:56
【问题描述】:

我在对查询中的字段进行分组时遇到问题。这是我所说的一个例子:

例子:

AIR_DT             DOL_GAP_TIME         MATL_SIZE                     
15-JAN-15          8:00 AM              30
15-JAN-15          8:00 AM              25
15-JAN-15          9:00 AM              5
15-JAN-15          9:00 AM              10
15-JAN-15          9:00 AM              5
15-JAN-15          9:00 AM              20

时间相同的应该归为一个,总结他们的matl_size

预期输出:

AIR_DT             DOL_GAP_TIME         MATL_SIZE                     
15-JAN-15          8:00 AM              55
15-JAN-15          9:00 AM              40

这是我的 SQL:

SELECT 
      a.air_dt, 
      TRIM(SUBSTR(TO_CHAR (a.dol_pref_start_time, 'mm/dd/yyyy hh:mi:ss AM'),12,2))
      || ':00 '
      || TRIM(SUBSTR (TO_CHAR (a.dol_pref_start_time, 'mm/dd/yyyy hh:mi:ss    AM'),
21, 2)) dol_gap_time, e.matl_size
FROM order_implem_dtl_broadcast a, matl_mstr b, matl_size_mstr e 
WHERE a.matl_id = b.matl_id 
AND b.matl_size_id = e.matl_size_id  
AND a.air_dt LIKE '%15-JAN-15%'
GROUP BY a.air_dt, a.dol_pref_start_time, e.matl_size
ORDER BY a.air_dt, a.dol_pref_start_time;

感谢您提前提供帮助!

【问题讨论】:

    标签: sql oracle oracle11g group-by oracle-sqldeveloper


    【解决方案1】:

    根据您的示例数据,这应该可以满足您的需求:

    select AIR_DT, DOL_GAP_TIME, sum(MATL_SIZE)
    from table t
    group by AIR_DT, DOL_GAP_TIME;
    

    但是,我不知道这与问题中的查询有什么关系。

    【讨论】:

    • 感谢 Gordon Linoff 的快速响应,查询包括 3 个表。我尝试将您的查询与我的查询混合,但不幸的是我仍然得到相同的结果。我在想,因为查询是按 a.dol_pref_start_time 值对它进行分组,我希望它按字符串聚合值 (dol_start_time) 对其进行分组。
    【解决方案2】:

    好的,让我们从您的初始查询开始:

    SELECT 
      a.air_dt, 
      TRIM(SUBSTR(TO_CHAR (a.dol_pref_start_time, 'mm/dd/yyyy hh:mi:ss AM'),12,2))
      || ':00 '
      || TRIM(SUBSTR (TO_CHAR (a.dol_pref_start_time, 'mm/dd/yyyy hh:mi:ss    AM'), 21, 2)) dol_gap_time, e.matl_size
      FROM order_implem_dtl_broadcast a, matl_mstr b, matl_size_mstr e 
     WHERE a.matl_id = b.matl_id 
       AND b.matl_size_id = e.matl_size_id  
       AND a.air_dt LIKE '%15-JAN-15%'
     GROUP BY a.air_dt, a.dol_pref_start_time, e.matl_size
     ORDER BY a.air_dt, a.dol_pref_start_time;
    

    我发现了几个问题。一,您按e.matl_size 分组,即使那是您想要SUM() 的列。你不希望它出现在GROUP BY 中。其次,您从dol_pref_start_time 获取时间的方式真的很奇怪。看起来你想四舍五入到小时,然后只得到小时加上是上午还是下午。所以这个:

    TRIM(SUBSTR(TO_CHAR (a.dol_pref_start_time, 'mm/dd/yyyy hh:mi:ss AM'),12,2))
      || ':00 '
      || TRIM(SUBSTR (TO_CHAR (a.dol_pref_start_time, 'mm/dd/yyyy hh:mi:ss    AM'), 21, 2)) dol_gap_time
    

    可以是这样的:

    TO_CHAR(TRUNC(a.dol_pref_start_time, 'HH'), 'HH:MI AM') AS dol_gap_time
    

    第三,您的日期是否存储为日期?如果是这样,你为什么要这样做?

    AND a.air_dt LIKE '%15-JAN-15%'
    

    这样做会更好:

    AND TRUNC(a.air_dt) = date'2015-01-15'
    

    或者,如果您在 a.air_dt 上有索引,则:

    AND a.air_dt >= date'2015-01-15'
    AND a.air_dt < date'2015-01-16'
    

    将所有这些放在一起,我们会得到这样的结果(请注意,我还将您的联接转换为 ANSI SQL 联接):

    SELECT TRUNC(a.air_dt) AS air_dt
         , TO_CHAR(TRUNC(a.dol_pref_start_time, 'HH'), 'HH:MI AM') AS dol_gap_time
         , SUM(e.matl_size) AS matl_size
      FROM order_implem_dtl_broadcast a INNER JOIN matl_mstr b
        ON a.matl_id = b.matl_id
     INNER JOIN matl_size_mstr e 
        ON b.matl_size_id = e.matl_size_id
     WHERE a.air_dt >= date'2015-01-15'
       AND a.air_dt < date'2015-01-16'
     GROUP BY TRUNC(a.air_dt), TO_CHAR(TRUNC(a.dol_pref_start_time, 'HH'), 'HH:MI AM')
     ORDER BY air_dt, TO_DATE(dol_gap_time, 'HH:MI AM'); -- using aliases in the ORDER BY, converting dol_gap_time to DATE for sorting
    

    【讨论】:

    • 谢谢大卫费伯。我修改了该代码并删除了 group by 子句中的 matl_size。是的,那是正确的,我想四舍五入到小时,我会尝试你所有的建议。这真的很有帮助。
    • 你好大卫。我尝试了您的查询,它可以总结 matl_size 并按 dol_gap_time 对其进行分组。我现在唯一的问题是如何将 dol_gap_time 排序为时间?我需要将 dol_gap_time 视为时间,目前我认为它被排序为字符串。我尝试在 order by 子句中使用 dol_gap_time 中的 to_date 函数,不幸的是它对我不起作用。
    • 忽略 dol_gap_time @David Faber 的排序。我尝试在另一个 by 子句中使用 to_date 函数并解决了我的时间排序问题。
    • 再次感谢大卫和帮助过的人。我会将此标记为已回答。给你们更多的权力!
    • @rgstamayo,感谢您指出ORDER BY 子句中的错误。我正在更新我的答案以使用TO_DATE(dol_gap_time, 'HH:MI AM')
    猜你喜欢
    • 2013-07-04
    • 2011-03-23
    • 1970-01-01
    • 1970-01-01
    • 2016-10-08
    • 2019-03-03
    • 2022-12-12
    • 2014-08-29
    • 2023-03-14
    相关资源
    最近更新 更多