【问题标题】:Oracle SQL Group By ifOracle SQL 分组依据 if
【发布时间】:2026-02-09 05:50:01
【问题描述】:

在我的应用程序中,我将打开的文件记录在下表中:

TESTID        SITE       LATEST_READ READ_COUNT FILE_ORIGIN_ID
------------- ---------- ----------- ---------- --------------
File1        |Site1     |02/05/13   |         2|             1 
File1        |Site2     |22/01/14   |         3|             2 
File2        |Site1     |02/06/14   |         8|             0 
File3        |Site1     |19/09/14   |        17|             0 
File4        |Site2     |19/09/14   |        14|             2 
File4        |Site2     |19/09/14   |        34|             1  
File4        |Site3     |19/09/14   |        10|             0 
File5        |Site2     |19/09/14   |        44|             2  
File5        |Site3     |19/09/14   |         1|             2 

如果文件的至少一个FILE_ORIGIN_ID2 不同,我想获得每个文件的读取计数总和。

这个例子应该给出:

TESTID        SITE       LATEST_READ SUM        FILE_ORIGIN_ID
------------- ---------- ----------- ---------- --------------
File1        |Site1     |02/05/13   |         5|             1 
File2        |Site1     |02/06/14   |         8|             0 
File3        |Site1     |19/09/14   |        17|             0 
File4        |Site2     |19/09/14   |        58|             X <-- can be 0 or 1 
File5        |Site2     |19/09/14   |        44|             2  
File5        |Site3     |19/09/14   |         1|             2 

我尝试了以下方法:

SELECT TESTID, SUM(READ_COUNT), LATEST_READ, FILE_ORIGIN_ID, site
FROM FILE_USAGE_LOG 
GROUP BY TESTID, TESTID, LATEST_READ, 
          CASE 
            WHEN FILE_ORIGIN_ID <> '2' Then 1
            ELSE 0
          END, site
ORDER BY TESTID;

但它并没有做我想做的事......我该如何改进呢?如果是分组行,我该如何将FILE_ORIGIN_ID 设置为 0 或 1

【问题讨论】:

  • 为什么file1的行合并了file5的行不合并?
  • @GordonLinoff 因为File5FILE_ORIGIN_ID 没有一个与2 不同
  • 这对我来说太混乱了......在派生表中执行 FILE_ORIGIN_ID CASE,然后 GROUP BY 它的结果。
  • 我认为文件5的SUM应该是44而不是58。
  • @Thomas 您需要所有字段吗?我可以只用 testid 和 read_count 的总和得到所需的结果,除非你可以给我一个聚合函数以用于其他函数(如 max、min 等......)

标签: sql oracle group-by


【解决方案1】:

现在我有一个部分结果,它将以您需要的格式返回 TESTID 和 READ_COUNT:

select testid, read_count FROM
(SELECT testid, sum(read_count) as  read_count
FROM FILE_USAGE_LOG
where testid in (select distinct testid from FILE_USAGE_LOG
                 where not file_origin_id = 2)
group by testid)
UNION
(select testid, read_count
 FROM FILE_USAGE_LOG
 where testid not in (select distinct testid from FILE_USAGE_LOG
                 where not file_origin_id = 2))
ORDER BY testid

这不是您想要的确切结果,因为对其他字段进行分组会给您带来不同的结果,但是如果您想获取除 testid 之外的任何其他数据(我们正在分组),您需要将这些在聚合函数中 编辑:添加不同的值(我认为合适的随机最小值或最大值)

select testid,site, read_count,latest_read,file_origin_id, grouped FROM 
(SELECT testid, MIN(site) as site,  sum(read_count) as  read_count
 , max(latest_read) as latest_read, min(file_origin_id) as file_origin_id
 ,'true' as grouped
FROM mytable
where testid in (select distinct testid from mytable
                 where not file_origin_id = 2)
group by testid)
UNION
(select testid, site, read_count, latest_read, file_origin_id, 'false' as grouped
 FROM mytable
 where testid not in (select distinct testid from mytable
                 where not file_origin_id = 2))
ORDER BY testid

FIDDLE

【讨论】:

    【解决方案2】:

    SQL Fiddle

    Oracle 11g R2 架构设置

    CREATE TABLE FILE_USAGE_LOG (TESTID, SITE, LATEST_READ, READ_COUNT, FILE_ORIGIN_ID ) AS
              SELECT 'File1', 'Site1', DATE '2013-05-02', 2, 1 FROM DUAL
    UNION ALL SELECT 'File1', 'Site2', DATE '2014-01-22', 3, 2 FROM DUAL
    UNION ALL SELECT 'File2', 'Site1', DATE '2014-06-02', 8, 0 FROM DUAL
    UNION ALL SELECT 'File3', 'Site1', DATE '2014-09-19', 17, 0 FROM DUAL
    UNION ALL SELECT 'File4', 'Site2', DATE '2014-09-19', 14, 2 FROM DUAL
    UNION ALL SELECT 'File4', 'Site2', DATE '2014-09-19', 34, 1 FROM DUAL
    UNION ALL SELECT 'File4', 'Site3', DATE '2014-09-19', 10, 0 FROM DUAL
    UNION ALL SELECT 'File5', 'Site2', DATE '2014-09-19', 44, 2 FROM DUAL
    UNION ALL SELECT 'File5', 'Site3', DATE '2014-09-19', 1, 2 FROM DUAL;
    

    查询 1

    SELECT  TESTID,
            REGEXP_REPLACE( 
              LISTAGG( SITE, ', ' )
                WITHIN GROUP( ORDER BY SITE ),
              '([^, ]+)(, \1)+($|, )',
              '\1\3'
            ) AS SITES, 
            MAX( LATEST_READ ) AS LATEST_READ,
            SUM(READ_COUNT) AS Total_Read_Count
    FROM    FILE_USAGE_LOG 
    GROUP BY
            TESTID
    HAVING  COUNT( CASE FILE_ORIGIN_ID WHEN 2 THEN NULL ELSE 1 END ) > 0
    UNION ALL
    SELECT  TESTID,
            SITE,
            LATEST_READ,
            READ_COUNT
    FROM    FILE_USAGE_LOG l
    WHERE   FILE_ORIGIN_ID = 2
    AND     NOT EXISTS ( SELECT 'X'
                         FROM   FILE_USAGE_LOG x
                         WHERE  x.TESTID      = l.TESTID
                         AND    x.FILE_ORIGIN_ID <> 2
                       )
    ORDER BY 1,2
    

    Results

    | TESTID |        SITES |                 LATEST_READ | TOTAL_READ_COUNT |
    |--------|--------------|-----------------------------|------------------|
    |  File1 | Site1, Site2 |   January, 22 2014 00:00:00 |                5 |
    |  File2 |        Site1 |      June, 02 2014 00:00:00 |                8 |
    |  File3 |        Site1 | September, 19 2014 00:00:00 |               17 |
    |  File4 | Site2, Site3 | September, 19 2014 00:00:00 |               58 |
    |  File5 |        Site2 | September, 19 2014 00:00:00 |               44 |
    |  File5 |        Site3 | September, 19 2014 00:00:00 |                1 |
    

    查询 2

    SELECT  TESTID,
            REGEXP_REPLACE( 
              LISTAGG( SITE, ', ' )
                WITHIN GROUP( ORDER BY SITE ),
              '([^, ]+)(, \1)+($|, )',
              '\1\3'
            ) AS SITES, 
            MAX( LATEST_READ ) AS LATEST_READ,
            SUM(READ_COUNT) AS Total_Read_Count
    FROM    FILE_USAGE_LOG 
    WHERE   TESTID NOT LIKE 'this%'
    AND     LATEST_READ BETWEEN DATE '2014-01-01' AND DATE '2014-12-31'
    GROUP BY
            TESTID
    HAVING  COUNT( CASE FILE_ORIGIN_ID WHEN 2 THEN NULL ELSE 1 END ) > 0
    UNION ALL
    SELECT  TESTID,
            SITE,
            LATEST_READ,
            READ_COUNT
    FROM    FILE_USAGE_LOG l
    WHERE   FILE_ORIGIN_ID = 2
    AND     NOT EXISTS ( SELECT 'X'
                         FROM   FILE_USAGE_LOG x
                         WHERE  x.TESTID      = l.TESTID
                         AND    x.FILE_ORIGIN_ID <> 2
                         AND    TESTID NOT LIKE 'this%'
                         AND    LATEST_READ BETWEEN DATE '2014-01-01' AND DATE '2014-12-31'
                       )
    AND     TESTID NOT LIKE 'this%'
    AND     LATEST_READ BETWEEN DATE '2014-01-01' AND DATE '2014-12-31'
    ORDER BY 1,2
    

    Results

    | TESTID |        SITES |                 LATEST_READ | TOTAL_READ_COUNT |
    |--------|--------------|-----------------------------|------------------|
    |  File1 |        Site2 |   January, 22 2014 00:00:00 |                3 |
    |  File2 |        Site1 |      June, 02 2014 00:00:00 |                8 |
    |  File3 |        Site1 | September, 19 2014 00:00:00 |               17 |
    |  File4 | Site2, Site3 | September, 19 2014 00:00:00 |               58 |
    |  File5 |        Site2 | September, 19 2014 00:00:00 |               44 |
    |  File5 |        Site3 | September, 19 2014 00:00:00 |                1 |
    

    【讨论】:

    • 太好了!现在我想对输出应用条件,比如日期比较和testID not like ...。我把它放在哪里? (在查询的第二部分)
    • @Thomas - 添加编辑以回答您的问题(TLDR - 随处可见)
    • 太棒了,你帮了我很多!