选择按查询不在分组中的表列

时间:2019-08-06 19:33:25

标签: sql oracle

我是后端开发的新手。我正在创建一个查询,该查询应返回具有给定id(EXTERNAL_IDs)以及最近修改日期的所有列。 ID(EXTERNAL_ID)可以重复。

因此,查询应返回具有最近修改日期的不同ID(EXTERNAL_ID)。

正在使用的数据库是ORACLE。

我有一个包含5列的表格:

ID  |  RATE  |  LAST_MODIFIED              | EXTERNAL_ID  |  NAME
----------------------------------------------------------------
1   |  25    |  2018-08-28 12:25:19.276000 | 58           |  ERIC
2   |  900   |  2016-08-31 16:57:25.617000 | 58           |  DAN
3   |  36    |  2019-03-14 15:30:05.708000 | 34           |  DAN
4   |  54    |  2017-05-13 13:20:09.500000 | 34           |  MAN
5   |  85    |  2019-09-09 11:50:37.518900 | 34           |  MAT
6   |  23    |  2018-08-28 12:25:19.276000 | 23           |  DOC

给出EXTERNAL_ID为58,34->查询应返回:

ID  |  RATE  |  LAST_MODIFIED              | EXTERNAL_ID  |  NAME
----------------------------------------------------------------
1   |  25    |  2018-08-28 12:25:19.276000 | 58           |  ERIC
5   |  85    |  2019-09-09 11:50:37.518900 | 34           |  MAT

我尝试过的查询是:

SELECT EXTERNAL_ID, MAX(LAST_MODIFIED) FROM MY_TABLE
WHERE EXTERNAL_ID = 58 OR EXTERNAL_ID = 34
GROUP BY EXTERNAL_ID

产生的结果

LAST_MODIFIED              | EXTERNAL_ID  
-----------------------------------------
2018-08-28 12:25:19.276000 | 58           
2019-09-09 11:50:37.518900 | 34        

我尝试使用

查询
SELECT ID, RATE, MAX(LAST_MODIFIED), EXTERNAL_ID, NAME FROM MY_TABLE
WHERE EXTERNAL_ID = 58 OR EXTERNAL_ID = 34
GROUP BY EXTERNAL_ID

这会导致错误。

我期望的结果是:

给出EXTERNAL_ID为58,34->查询应返回:

ID  |  RATE  |  LAST_MODIFIED              | EXTERNAL_ID  |  NAME
----------------------------------------------------------------
1   |  25    |  2018-08-28 12:25:19.276000 | 58           |  ERIC
5   |  85    |  2019-09-09 11:50:37.518900 | 34           |  MAT

4 个答案:

答案 0 :(得分:1)

如果您需要id和rate的值以对应最大的last_moodified最大值,则应将内部联接与子查询一起使用max

  select  MY_TABLE.ID, MY_TABLE.RATE, T.max_mod, t.EXTERNAL_ID
  from  MY_TABLE 
  INNER JOIN  (
      SELECT EXTERNAL_ID, MAX(LAST_MODIFIED)  max_mod FROM MY_TABLE
      WHERE EXTERNAL_ID = 58 OR EXTERNAL_ID = 34
      GROUP BY EXTERNAL_ID
  ) t on t.EXTERNAL_ID = MY_TABLE.EXTERNAL_ID 
          AND t.max_mod = MY_TABLE.LAST_MODIFIED 

答案 1 :(得分:0)

使用不存在很容易:

SELECT t.* FROM MY_TABLE t
WHERE t.EXTERNAL_ID IN (58, 34)
AND NOT EXISTS (
  SELECT 1 FROM MY_TABLE m
  WHERE m.EXTERNAL_ID = t.EXTERNAL_ID AND m.LAST_MODIFIED > t.LAST_MODIFIED
) 

请参见demo

答案 2 :(得分:0)

另一种选择是使用分析功能

SELECT id,
       rate,
       last_modified,
       external_id,
       name
  FROM (
        SELECT t.id,
               t.rate,
               t.last_modified,
               t.external_id,
               t.name, 
               row_number() over (partition by external_id 
                                      order by last_modified desc) rn
          FROM MY_TABLE
         WHERE EXTERNAL_ID in( 34, 58 )
        )
 WHERE rn = 1

答案 3 :(得分:0)

您可以使用keep和density_rank一次选择:

select max(id) keep (dense_rank first order by last_modified desc) id,
       max(rate) keep (dense_rank first order by last_modified desc) rate,
       max(last_modified) keep (dense_rank first order by last_modified desc) last_modified,
       external_id,
       max(name) keep (dense_rank first order by last_modified desc) name
  from t
 where external_id in (34, 58)
 group by external_id;

示例执行:

FSITJA@db01> with t (id, rate, last_modified, external_id, name) as (
  2  select 1, 25 , to_timestamp('2018-08-28 12:25:19.276000', 'YYYY-MM-DD HH24:MI:SS.FF6'), 58, 'ERIC' from dual union all
  3  select 2, 900, to_timestamp('2016-08-31 16:57:25.617000', 'YYYY-MM-DD HH24:MI:SS.FF6'), 58, 'DAN'  from dual union all
  4  select 3, 36 , to_timestamp('2019-03-14 15:30:05.708000', 'YYYY-MM-DD HH24:MI:SS.FF6'), 34, 'DAN'  from dual union all
  5  select 4, 54 , to_timestamp('2017-05-13 13:20:09.500000', 'YYYY-MM-DD HH24:MI:SS.FF6'), 34, 'MAN'  from dual union all
  6  select 5, 85 , to_timestamp('2019-09-09 11:50:37.518900', 'YYYY-MM-DD HH24:MI:SS.FF6'), 34, 'MAT'  from dual union all
  7  select 6, 23 , to_timestamp('2018-08-28 12:25:19.276000', 'YYYY-MM-DD HH24:MI:SS.FF6'), 23, 'DOC'  from dual
  8  ) -- end of sample data
  9  select max(id) keep (dense_rank first order by last_modified desc) id,
 10         max(rate) keep (dense_rank first order by last_modified desc) rate,
 11         max(last_modified) keep (dense_rank first order by last_modified desc) last_modified,
 12         external_id,
 13         max(name) keep (dense_rank first order by last_modified desc) name
 14    from t
 15   where external_id in (34, 58)
 16   group by external_id;

        ID       RATE LAST_MODIFIED                                                               EXTERNAL_ID NAME
---------- ---------- --------------------------------------------------------------------------- ----------- ----
         5         85 2019-09-09 11:50:37.518900000                                                        34 MAT
         1         25 2018-08-28 12:25:19.276000000                                                        58 ERIC