【问题标题】:Create a row based on data from two rows根据两行的数据创建一行
【发布时间】:2021-08-02 20:09:16
【问题描述】:

我查看了以前的类似问题,但找不到这个确切的场景。我不是想将两行中的数据连接成一列。我正在尝试根据两行的数据构建一行。我不确定这是否可以通过内置的 oracle 函数完成,或者它需要是自定义函数。以下表为例。

create table reporttable( Location varchar2(10), Manager varchar2(10), ManagerType varchar2(1), User_Id Number, Region varchar2(10)); 

insert into reporttable select USA, 'Robert', 'A', '123', 'East'  from dual;
insert into reporttable select USA, 'Unknown', 'A', '123', 'Unknown'  from dual;
commit;

  Location  Manager     ManagerType  User_Id Region 
        USA Robert             A      123    Unknown
        USA Unknown            A      123    East

我想要的输出是这样的,因为 ManagerTypeUser_Id 表明它是同一个 Manager

Location  Manager     ManagerType  User_Id Region 
      USA Robert             A      123    East  

【问题讨论】:

  • 如果任何行没有匹配的 'not unknow' 条目,您希望显示它吗?
  • 是的,可能有一行在另一行中没有匹配的 managerType/User_Id。在这种情况下,我需要显示该行

标签: sql oracle select


【解决方案1】:

假设您要更新所有重复项以仅保留一行并删除其他行,并且保留的 managerregion 值应该是最大的非未知值,那么您可以使用:

MERGE INTO reporttable dst
USING (
  SELECT rowid AS rid,
         COALESCE(
           MAX( DECODE( manager, 'Unknown', NULL, manager ) ) OVER (
             PARTITION BY location, user_id, managertype
           ),
           'Unknown'
         ) AS manager,
         COALESCE(
           MAX( DECODE( region, 'Unknown', NULL, region ) ) OVER (
             PARTITION BY location, user_id, managertype
           ),
           'Unknown'
         ) AS region,
         ROW_NUMBER() OVER (
           PARTITION BY location, user_id, managertype
           ORDER BY ROWNUM
         ) AS rn,
         COUNT(*) OVER (
           PARTITION BY location, user_id, managertype
         ) AS cnt
  FROM   reporttable
) src
ON ( src.rid = dst.ROWID AND src.cnt > 1 )
WHEN MATCHED THEN
  UPDATE
  SET manager = src.manager,
      region  = src.region
  DELETE WHERE src.rn > 1;

其中,对于您的示例数据:

create table reporttable(
  Location varchar2(10),
  Manager varchar2(10),
  ManagerType varchar2(1),
  User_Id Number,
  Region varchar2(10)
);
insert into reporttable
select 'USA', 'Robert', 'A', '123', 'East'  from dual union all
select 'USA', 'Unknown', 'A', '123', 'Unknown'  from dual;

然后在MERGE之后:

SELECT * FROM reporttable;

输出:

LOCATION MANAGER MANAGERTYPE USER_ID REGION
USA Robert A 123 East

如果你只是想从表中SELECT,那么你可以使用相同的方法,只在每个分区内过滤ROW_NUMBER

SELECT location,
       manager,
       managertype,
       user_id,
       region
FROM   (
  SELECT location,
         COALESCE(
           MAX( DECODE( manager, 'Unknown', NULL, manager ) ) OVER (
             PARTITION BY location, user_id, managertype
           ),
           'Unknown'
         ) AS manager,
         managertype,
         user_id,
         COALESCE(
           MAX( DECODE( region, 'Unknown', NULL, region ) ) OVER (
             PARTITION BY location, user_id, managertype
           ),
           'Unknown'
         ) AS region,
         ROW_NUMBER() OVER (
           PARTITION BY location, user_id, managertype
           ORDER BY ROWNUM
         ) AS rn
  FROM   reporttable
) 
WHERE rn = 1

db小提琴here

【讨论】:

  • 一个问题,如果有唯一的行没有其他行的位置、user_id 和 managertype 是重复的,这会起作用吗?
  • @MSkiLLz 你可以试试看db<>fiddle
猜你喜欢
  • 1970-01-01
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-17
  • 2017-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多