SQL min()max()函数有异常

时间:2016-06-27 10:04:22

标签: sql oracle

这是我简洁的代码:

SELECT 
   a.user_id as User_ID,
   min(b.a_day) as Date_from,
   max(b.a_day) as Date_to,
   c.code as ID 
FROM a, b, c 
WHERE 
   a_day > (day, -15, getdate())
GROUP BY 
   a.user_id,
   c.code

Query提供以下输出:

User ID date_from   date_to     id    
1234567 2016-06-13  2016-06-13  B
1234567 2016-06-17  2016-06-17  A
12345672016-06-18  2016-06-18  A
1234567 2016-06-19  2016-06-19  A
1234567 2016-06-20  2016-06-20  A
1234567 2016-06-21  2016-06-21  B

我需要这样的东西:

User ID date_from   date_to     id
1234567 2016-06-13  2016-06-13  B
1234567 2016-06-17  2016-06-20  A
1234567 2016-06-21  2016-06-21  B

当我将min()和max()函数与group by一起使用时,它会对ID = A的所有记录进行精确聚合,但ID = B应该有异常。我必须每天只汇总具有相同ID的日期。

有什么想法吗?

提前致谢。

3 个答案:

答案 0 :(得分:3)

您可以使用以下策略合并这些行:

  1. 确定新分组的开始位置。
  2. 执行(1)中的标志的累积总和以识别每个分组。
  3. 然后进行聚合。
  4. 这看起来像:

    select min(date_from) as date_from, max(date_to) as date_to, id
    from (select t.*,
                 sum(isNewGroup) over (partition by id order by date_from) as grp
          from (select t.*,
                       (case when lag(date_to) over (partition by id order by date_from) >= date_from
                             then 0 else 1
                        end) as isNewGroup
                from t
               ) t
          ) t
    group by id, grp;
    

答案 1 :(得分:0)

这是我获得最小/最大连续日期的解决方案。

尝试在你的oracle中运行SQL。

对你有帮助吗?

WITH TEST_DATA AS (
    SELECT TO_DATE('20160613', 'YYYYMMDD') AS DATE_FROM, TO_DATE('20160613', 'YYYYMMDD') AS DATE_TO, 'B' AS ID FROM DUAL
    UNION ALL
    SELECT TO_DATE('20160617', 'YYYYMMDD') AS DATE_FROM, TO_DATE('20160617', 'YYYYMMDD') AS DATE_TO, 'A' AS ID FROM DUAL
    UNION ALL
    SELECT TO_DATE('20160618', 'YYYYMMDD') AS DATE_FROM, TO_DATE('20160618', 'YYYYMMDD') AS DATE_TO, 'A' AS ID FROM DUAL
    UNION ALL
    SELECT TO_DATE('20160619', 'YYYYMMDD') AS DATE_FROM, TO_DATE('20160619', 'YYYYMMDD') AS DATE_TO, 'A' AS ID FROM DUAL
    UNION ALL
    SELECT TO_DATE('20160620', 'YYYYMMDD') AS DATE_FROM, TO_DATE('20160620', 'YYYYMMDD') AS DATE_TO, 'A' AS ID FROM DUAL
    UNION ALL
    SELECT TO_DATE('20160621', 'YYYYMMDD') AS DATE_FROM, TO_DATE('20160621', 'YYYYMMDD') AS DATE_TO, 'B' AS ID FROM DUAL
)
SELECT 
    MIN(ID) AS ID,
    MIN(DATE_FROM) AS DATE_FROM,
    MAX(DATE_TO) AS DATE_TO
FROM (
    SELECT
        CONNECT_BY_ROOT(DATE_FROM) || CONNECT_BY_ROOT(ID) AS GROUP_KEY,
        ROW_NUMBER() OVER(PARTITION BY ID, DATE_FROM, DATE_TO ORDER BY ID, LEVEL DESC) AS DISTINCT_FLG,
        DATE_FROM, 
        DATE_TO, 
        ID
    FROM
        TEST_DATA
    WHERE ID = CONNECT_BY_ROOT(ID)
        CONNECT BY DATE_FROM = PRIOR DATE_TO + 1
    ORDER BY DATE_FROM
)
WHERE
    DISTINCT_FLG = 1
GROUP BY
    GROUP_KEY

答案 2 :(得分:-1)

这是mysql解决方案:

select grp, min(f) f, max(t) t, i 
from
(
    select x.*
    ,case when @lastu = i and datediff(f, @lastf)=1 then @gr:=@gr else @gr:=@gr+1 end grp
    ,@lastu:= i
    ,@lastf:= f
    from 
    (
        select '2016-06-13' f,'2016-06-13' t ,'B' i union all
        select '2016-06-17','2016-06-17','A' union all
        select '2016-06-18','2016-06-18','A' union all
        select '2016-06-19','2016-06-19','A' union all
        select '2016-06-20','2016-06-20','A' union all
        select '2016-06-21','2016-06-21','B'
        order by i, f, t
    ) x
    , (select @gr:=0, @lastu:='', @lastf:='' ) b
) xx
group by grp, i