【问题标题】:Move Non-NULL Values Up Within Partition在分区内向上移动非 NULL 值
【发布时间】:2019-08-15 19:31:24
【问题描述】:

不确定标题是否有意义,但这是我的问题以及我是如何到达现在的位置的。

背景:我在一对多设置中有 2 个表。 many 表可以有任意数量的记录,这些记录与一个表相关联,但有一个附加列,可以将许多记录标识为 1-7 之间的任何值。我用 7 个 CTE “收集”了每个组 1-7 的所有行,然后将它们连接到一个表中,让我了解我的示例数据。

如果单个列中的所有行都为空,那么我想显示一个 *,否则显示每个 GROUPID/GROUPNAME 的每一列中的所有不同值。我有点破解并削减了获得我想要的东西的方式,但有一个警告。如果可能的话,我想在 GROUPID/GROUPNAME 中分别对每一列进行排序,这样 NULL 就不会出现在数据的中间。

这是我的代码,让我陷入困境:

WITH SAMPLEDATA (CYCLEID,GROUPID,GROUPNAME,COL1,COL2,COL3,COL4,COL5,COL6,COL7)
AS (
SELECT 1,7669,'000000261','GAS',NULL,NULL,NULL,'1',NULL,'00' FROM DUAL
UNION ALL
SELECT 2,7669,'000000261','GAS',NULL,NULL,NULL,'1',NULL,'000000261' FROM DUAL
UNION ALL
SELECT 3,7669,'000000261','GAS',NULL,NULL,NULL,'Chester',NULL,'00' FROM DUAL
UNION ALL
SELECT 4,7669,'000000261','GAS',NULL,NULL,NULL,'Chester',NULL,'000000261' FROM DUAL
UNION ALL
SELECT 5,7669,'000000261','GFG',NULL,NULL,NULL,'1',NULL,'00' FROM DUAL
UNION ALL
SELECT 6,7669,'000000261','GFG',NULL,NULL,NULL,'1',NULL,'000000261' FROM DUAL
UNION ALL
SELECT 7,7669,'000000261','GFG',NULL,NULL,NULL,'Chester',NULL,'00' FROM DUAL
UNION ALL
SELECT 8,7669,'000000261','GFG',NULL,NULL,NULL,'Chester',NULL,'000000261' FROM DUAL
UNION ALL
SELECT 9,7669,'000000261','GKE',NULL,NULL,NULL,'1',NULL,'00' FROM DUAL
UNION ALL
SELECT 10,7669,'000000261','GKE',NULL,NULL,NULL,'1',NULL,'000000261' FROM DUAL
UNION ALL
SELECT 11,7669,'000000261','GKE',NULL,NULL,NULL,'Chester',NULL,'00' FROM DUAL
UNION ALL
SELECT 12,7669,'000000261','GKE',NULL,NULL,NULL,'Chester',NULL,'000000261' FROM DUAL
 ) 
 , GROUPSPROCESSED AS (
SELECT
  GROUPID,
  GROUPNAME,
  CASE
    WHEN cycleid = 1
    THEN NVL(COL1,'*')
    WHEN COL1 = FIRST_VALUE(COL1) OVER (PARTITION BY GROUPNAME ORDER BY GROUPNAME, COL1)
    THEN NULL
    WHEN COL1 = LAG(COL1) OVER (PARTITION BY GROUPNAME ORDER BY GROUPNAME, COL1)
    THEN NULL
    ELSE COL1
  END AS "COL1",
  CASE
    WHEN cycleid = 1
    THEN NVL(COL2,'*')
    WHEN COL2 = FIRST_VALUE(COL2) OVER (PARTITION BY GROUPNAME ORDER BY GROUPNAME, COL2)
    THEN NULL
    WHEN COL2 = LAG(COL2) OVER (PARTITION BY GROUPNAME ORDER BY GROUPNAME, COL2)
    THEN NULL
    ELSE COL2
  END AS "COL2",
  CASE
    WHEN cycleid = 1
    THEN NVL(COL3,'*')
    WHEN COL3 = FIRST_VALUE(COL3) OVER (PARTITION BY GROUPNAME ORDER BY GROUPNAME, COL3)
    THEN NULL
    WHEN COL3 = LAG(COL3) OVER (PARTITION BY GROUPNAME ORDER BY GROUPNAME, COL3)
    THEN NULL
    ELSE COL3
  END AS "COL3",
  CASE
    WHEN cycleid = 1
    THEN NVL(COL4,'*')
    WHEN COL4 = FIRST_VALUE(COL4) OVER (PARTITION BY GROUPNAME ORDER BY GROUPNAME, COL4)
    THEN NULL
    WHEN COL4 = LAG(COL4) OVER (PARTITION BY GROUPNAME ORDER BY GROUPNAME, COL4)
    THEN NULL
    ELSE COL4
  END AS "COL4",
  CASE
    WHEN cycleid = 1
    THEN NVL(COL5,'*')
    WHEN COL5 = FIRST_VALUE(COL5) OVER (PARTITION BY GROUPNAME ORDER BY GROUPNAME, COL5)
    THEN NULL
    WHEN COL5 = LAG(COL5) OVER (PARTITION BY GROUPNAME ORDER BY GROUPNAME, COL5)
    THEN NULL
    ELSE COL5
  END AS "COL5",
  CASE
    WHEN cycleid = 1
    THEN NVL(COL6,'*')
    WHEN COL6 = FIRST_VALUE(COL6) OVER (PARTITION BY GROUPNAME ORDER BY GROUPNAME, COL6)
    THEN NULL
    WHEN COL6 = LAG(COL6) OVER (PARTITION BY GROUPNAME ORDER BY GROUPNAME, COL6)
    THEN NULL
    ELSE COL6
  END AS "COL6",
  CASE
    WHEN cycleid = 1
    THEN NVL(COL7,'*')
    WHEN COL7 = FIRST_VALUE(COL7) OVER (PARTITION BY GROUPNAME ORDER BY GROUPNAME, COL7)
    THEN NULL
    WHEN COL7 = LAG(COL7) OVER (PARTITION BY GROUPNAME ORDER BY GROUPNAME, COL7)
    THEN NULL
    ELSE COL7
  END AS "COL7"
FROM SAMPLEDATA)
SELECT * FROM GROUPSPROCESSED
WHERE COALESCE (COL1,COL2,COL3,COL4,COL5,COL6,COL7) IS NOT NULL
ORDER BY 1,2,3,4,5,6,7,8,9

电流输出:

期望的输出:

编辑 这是在任何操作之前从我的示例中导入确切原始数据的代码。从技术上讲,我需要将 3 个表绑定在一起才能得出上面的输出。

GROUPPROFILE 包含我上面输出中字段 1-2 的 ID 和 NAME。

COLVALUES 保存基于 COLLEVELID 为 1-7 的输出中其余字段的数据 (NAME)

GROUPCOLMM表只是用来连接GROUPPROFILE.GROUPPROFILEID > COLVALUES.COLVALUEID

CREATE TABLE GROUPPROFILE (GROUPPROFILEID NUMBER(12), SHORTNM NVARCHAR2(30))
REM INSERTING into GROUPPROFILE
Insert into GROUPPROFILE (GROUPPROFILEID,SHORTNM) values (7669,'000000261');

CREATE TABLE COLVALUES (COLVALUEID NUMBER(12), NAME NVARCHAR2(50), COLLEVELID NUMBER(12))
REM INSERTING into COLVALUES
Insert into COLVALUES (COLVALUEID,NAME,COLLEVELID) values (18901,'GFG',1);
Insert into COLVALUES (COLVALUEID,NAME,COLLEVELID) values (106,'GKE',1);
Insert into COLVALUES (COLVALUEID,NAME,COLLEVELID) values (1351,'GAS',1);
Insert into COLVALUES (COLVALUEID,NAME,COLLEVELID) values (423,'0',4);
Insert into COLVALUES (COLVALUEID,NAME,COLLEVELID) values (1,'1',5);
Insert into COLVALUES (COLVALUEID,NAME,COLLEVELID) values (18514,'Chester',5);

CREATE TABLE GROUPCOLMM (GROUPPROFILEID NUMBER(12), COLVALUEID NUMBER(12))
REM INSERTING into GROUPCOLMM
Insert into GROUPCOLMM (GROUPPROFILEID,COLVALUEID) values (7669,1);
Insert into GROUPCOLMM (GROUPPROFILEID,COLVALUEID) values (7669,3);
Insert into GROUPCOLMM (GROUPPROFILEID,COLVALUEID) values (7669,106);
Insert into GROUPCOLMM (GROUPPROFILEID,COLVALUEID) values (7669,1351);
Insert into GROUPCOLMM (GROUPPROFILEID,COLVALUEID) values (7669,16503);
Insert into GROUPCOLMM (GROUPPROFILEID,COLVALUEID) values (7669,18514);
Insert into GROUPCOLMM (GROUPPROFILEID,COLVALUEID) values (7669,18901);

【问题讨论】:

  • 我想你把自己画到了一个角落里。我们可以备份并从原始数据开始吗?您最好先进行区分和排序,然后将所有内容放入七列中。
  • 当然我想这样做,但最好。我可以从一开始就创建一些原始样本数据。这可能需要我几个小时,但一旦我准备好我就会发布它。
  • 我已经编辑了原始帖子以在底部包含原始样本数据。感谢您抽出宝贵时间查看此内容。

标签: sql oracle plsql oracle11g


【解决方案1】:

您无法从您发布的“原始”数据中获取示例数据。我从子查询 ORIGINALDATA 中的示例数据中对原始数据进行了逆向工程,然后提出了这个解决方案:

WITH SAMPLEDATA (CYCLEID,GROUPID,GROUPNAME,COL1,COL2,COL3,COL4,COL5,COL6,COL7)
AS (
SELECT 1,7669,'000000261','GAS',NULL,NULL,NULL,'1',NULL,'00' FROM DUAL
UNION ALL
SELECT 2,7669,'000000261','GAS',NULL,NULL,NULL,'1',NULL,'000000261' FROM DUAL
UNION ALL
SELECT 3,7669,'000000261','GAS',NULL,NULL,NULL,'Chester',NULL,'00' FROM DUAL
UNION ALL
SELECT 4,7669,'000000261','GAS',NULL,NULL,NULL,'Chester',NULL,'000000261' FROM DUAL
UNION ALL
SELECT 5,7669,'000000261','GFG',NULL,NULL,NULL,'1',NULL,'00' FROM DUAL
UNION ALL
SELECT 6,7669,'000000261','GFG',NULL,NULL,NULL,'1',NULL,'000000261' FROM DUAL
UNION ALL
SELECT 7,7669,'000000261','GFG',NULL,NULL,NULL,'Chester',NULL,'00' FROM DUAL
UNION ALL
SELECT 8,7669,'000000261','GFG',NULL,NULL,NULL,'Chester',NULL,'000000261' FROM DUAL
UNION ALL
SELECT 9,7669,'000000261','GKE',NULL,NULL,NULL,'1',NULL,'00' FROM DUAL
UNION ALL
SELECT 10,7669,'000000261','GKE',NULL,NULL,NULL,'1',NULL,'000000261' FROM DUAL
UNION ALL
SELECT 11,7669,'000000261','GKE',NULL,NULL,NULL,'Chester',NULL,'00' FROM DUAL
UNION ALL
SELECT 12,7669,'000000261','GKE',NULL,NULL,NULL,'Chester',NULL,'000000261' FROM DUAL
 ) 
, originaldata as (
  select distinct groupid, groupname, col, val from sampledata
  unpivot (val for col in (COL1 as 1,COL2 as 2,COL3 as 3,COL4 as 4,COL5 as 5,COL6 as 6,COL7 as 7))
)
select GROUPID, GROUPNAME, 
  case when rn = 1 and col1 is null then '*' else col1 end col1,
  case when rn = 1 and col2 is null then '*' else col2 end col2,
  case when rn = 1 and col3 is null then '*' else col3 end col3,
  case when rn = 1 and col4 is null then '*' else col4 end col4,
  case when rn = 1 and col5 is null then '*' else col5 end col5,
  case when rn = 1 and col6 is null then '*' else col6 end col6,
  case when rn = 1 and col7 is null then '*' else col7 end col7
from (
  select o.*,
  row_number() over(partition by groupid, groupname, col order by val) rn
  from originaldata o
)
pivot(
  max(val) 
  for col in (1 as COL1,2 as COL2,3 as COL3,4 as COL4,5 as COL5,6 as COL6,7 as COL7)
)
order by groupid, groupname, rn;

   GROUPID GROUPNAME COL1      COL2      COL3      COL4      COL5      COL6      COL7     
---------- --------- --------- --------- --------- --------- --------- --------- ---------
      7669 000000261 GAS       *         *         *         1         *         00       
      7669 000000261 GFG                                     Chester             000000261
      7669 000000261 GKE                                   

最好的问候, 炖阿什顿

【讨论】:

  • 没有看到你的我做了几乎相同的解决方案。看起来不错,虽然我喜欢这个 OP 的 hack'n'slash 版本;)
  • 感谢大家的意见和 Stew Ashton 的解决方案。我已将您的 unpivot > pivot 方法插入到我预先存在的查询的底部,它正在做我想要的。到目前为止,我已经筛选了几百条记录,没有发现任何差异。标记为答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-20
  • 1970-01-01
相关资源
最近更新 更多