Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如果所有列都返回null或仅返回非null列,如何返回一条记录_Sql_Oracle_Plsql - Fatal编程技术网

Sql 如果所有列都返回null或仅返回非null列,如何返回一条记录

Sql 如果所有列都返回null或仅返回非null列,如何返回一条记录,sql,oracle,plsql,Sql,Oracle,Plsql,我需要一种方法来处理以下场景 编写一个查询以转换以下结果集 ID|Location|NameA|ValueA|NameB|ValueB|NameC|ValueC|NameD|ValueD| __|________|_____|______|_____|______|_____|______|_____|______| 0 | BL |NULL |NULL |NULL |NULL |NULL |NULL |NULL |NULL | __|________|_____|______

我需要一种方法来处理以下场景

编写一个查询以转换以下结果集

ID|Location|NameA|ValueA|NameB|ValueB|NameC|ValueC|NameD|ValueD|
__|________|_____|______|_____|______|_____|______|_____|______|
0 |   BL   |NULL |NULL  |NULL |NULL  |NULL |NULL  |NULL |NULL  | 
__|________|_____|______|_____|______|_____|______|_____|______|
1 |   GT   |x    |y     |NULL |NULL  |s    |z     |NULL |NULL  |
__|________|_____|______|_____|______|_____|______|_____|______|
2 |   SZ   |c    |d     |e    |f     |NULL |NULL  |NULL |NULL  | 
__|________|_____|______|_____|______|_____|______|_____|______|
…到这个

ID|Location|Name |Value |
__|________|_____|______|
0 |   BL   |NULL |NULL  |
__|________|_____|______|
1 |   GT   |x    |y     |
__|________|_____|______|
1 |   GT   |s    |z     |
__|________|_____|______|
2 |   SZ   |c    |d     |
 _|________|_____|______|
2 |   SZ   |e    |f     |
  • 对于包含所有空“Name/Value”列的记录,我不希望结果表中有四条记录,我只希望有一条
  • 对于具有多个非空名称/值对的记录,我希望它们显示为结果表的单独记录,并忽略空名称/值对
  • 例如,如果NameA不为null,ValueA为null,则根据原始场景,它将从结果表中丢弃
编辑: 我决定使用您的交叉应用选项,但在实施时遇到困难, 我将粘贴更改了表名的原始查询,以便Gordon或其他人可以提供帮助

select t.CADID, t.TECHNOLOGYTYPE, t.ACCESSSUPPLIER, t.LOCATION, t.LOCATIONTYPE, t.NETWORKTYPE, t.ACCESSTYPE, t.CARRIERTYPE, t.MAXDOWNSPEED, t.MAXUPSPEED, v.NAME, v.VALUE 
from( TableA t 
LEFT OUTER JOIN TableB VIEW0 ON (VIEW0.access_supplier = t.access_supplier
                                            AND VIEW0.network_type = t.network_type
                                            AND VIEW0.address_location_type_map_id = t.address_location_type_map_id
                                            AND VIEW0.NAME = 'Nls-type')
LEFT OUTER JOIN TableB VIEW1 ON (VIEW1.access_supplier = t.access_supplier
                                           AND VIEW1.network_type = t.network_type
                                            AND VIEW1.address_location_type_map_id = t.address_location_type_map_id
                                            AND VIEW1.NAME = 'NL-type')
LEFT OUTER JOIN TableB VIEW2 ON (VIEW2.access_supplier = t.access_supplier
                                            AND VIEW2.network_type = t.network_type
                                            AND VIEW2.address_location_type_map_id = t.address_location_type_map_id
                                            AND VIEW2.NAME = 'Net-type')
LEFT OUTER JOIN TableB VIEW3 ON (VIEW3.access_supplier = t.access_supplier
                                            AND VIEW3.network_type = t.network_type
                                            AND VIEW3.address_location_type_map_id = t.address_location_type_map_id
                                            AND VIEW3.NAME = 'Interconnect-level')
LEFT OUTER JOIN TableB VIEW4 ON (VIEW4.access_supplier = t.access_supplier
                                            AND VIEW4.network_type = t.network_type
                                            AND VIEW4.address_location_type_map_id = t.address_location_type_map_id
                                            AND VIEW4.NAME = 'FTU-type')
LEFT OUTER JOIN TableB VIEW5 ON (VIEW5.access_supplier = t.access_supplier
                                            AND VIEW5.network_type = t.network_type
                                            AND VIEW5.address_location_type_map_id = t.address_location_type_map_id
                                            AND VIEW5.NAME = 'Area-type')
 )WHERE (t.cad_id = '237864868')
cross apply
     (values ('a', VIEW0.name as name0, VIEW0.value as vaue0),
             ('b', VIEW1.name as name1, VIEW1.valueb as value1),
             ('c', VIEW2.name as name2, VIEW2.valuec as value2),
             ('d', VIEW3.name as name3, VIEW3.valued as value3)
     ) v(which, name, value)
where v.name is not null or
      (v.which = 'a' and
       v.name0 is null and v.name1 is null and v.name2 is null and v.name3 is null
      );

只需使用
联合
,如下所示:

select ID,Location,NameA,ValueA from table where NameA is not null
union
select ID,Location,NameB,ValueB from table where NameB is not null
union
select ID,Location,NameC,ValueC from table where NameC is not null
union
select ID,Location,NameD,ValueD from table where NameD is not null
union
select ID,Location,null,null from table where coalesce(NameA,NameB,NameC,NameD) is null

或者您可以按如下方式使用
UNPIVOT

-- Sample Data:
WITH dat(ID,Location,NameA,ValueA,NameB,ValueB,NameC,ValueC,NameD,ValueD) AS
  (SELECT 0 ,   'BL'   ,NULL ,NULL  ,NULL ,NULL,NULL ,NULL,NULL ,NULL  FROM dual
    UNION
   SELECT 1 ,   'GT'   ,'x'  ,'y'   ,NULL ,NULL,'s'  , 'z',NULL ,NULL  FROM dual
    UNION
   SELECT 2 ,   'SZ'   ,'c'  ,'d'   ,'e'  ,'f' ,NULL ,NULL,NULL ,NULL  FROM dual)
-- SQL-Statement:
SELECT id,location, NAME, VALUE 
  FROM (
    SELECT id,location, NAME, VALUE,sk, MAX(NAME) over (PARTITION BY id) max_name
      FROM dat
      UNPIVOT INCLUDE NULLS(
        (NAME, VALUE) FOR sk IN ((NameA, ValueA) AS 1
                                ,(NameB, ValueB) AS 2
                                ,(NameC, ValueC) AS 3
                                ,(NameD, ValueD) AS 4)
      )
)
WHERE (SK = 1 AND max_name IS NULL)
   OR NAME IS NOT NULL

试试这个。

Oracle中最简单的答案可能是:

select t.id, t.namea as name. t.valuea as valuea
from t
where t.namea is not null or 
      (t.namea is null and t.nameb is null and t.namec is null and t.named is null)
union all
select t.id, t.nameb as name. t.valueb as valuea
from t
where t.nameb is not null 
union all
select t.id, t.namec as name. t.valuec as valuea
from t
where t.namec is not null 
union all
select t.id, t.named as name. t.valued as valuea
from t
where t.named is not null ;
出于某种原因(可能是荒谬的原因),我在下面给出了答案,认为这个问题被标记为SQL Server。Oracle12c支持横向联接,因此下面的内容可以适用于Oracle语法

我把剩下的答案留在这里

select t.id, v.name, v.value
from t cross apply
     (values ('a', t.namea, t.valuea),
             ('b', t.nameb, t.valueb),
             ('c', t.namec, t.valuec),
             ('d', t.named, t.valued)
     ) v(which, name, value)
where v.name is not null or
      (v.which = 'a' and

      );
我喜欢使用
交叉应用
取消IVOT。因此,基本的unpivot是:

select t.id, v.name, v.value
from t cross apply
     (values (t.namea, t.valuea), (t.nameb, t.valueb), (t.namec, t.valuec), (t.named, t.valued)
     ) v(name, value);
然后,您需要一个条件,如果它是所有值,则
null
仅显示一次。您可以为此使用窗口功能:

select id, name, value
from (select t.id, v.name, v.value,
             count(*) over (partition by t.id, v.name, v.value) as cnt_nv,
             row_number() over (order by t.id) as seqnum
      from t cross apply
           (values (t.namea, t.valuea), (t.nameb, t.valueb), (t.namec, t.valuec), (t.named, t.valued)
           ) v(name, value)
     ) v
where name is not null or
      (cnt_nv = 4 and seqnum = 1);
如果您只关心
name
是否为
NULL
,或者是否希望
name
value
都为
NULL
,我就有点不清楚了。任何一种逻辑都可以实现;只是不清楚你想要哪个

编辑:

也可以在不使用子查询的情况下执行此操作:

select t.id, v.name, v.value
from t cross apply
     (values ('a', t.namea, t.valuea),
             ('b', t.nameb, t.valueb),
             ('c', t.namec, t.valuec),
             ('d', t.named, t.valued)
     ) v(which, name, value)
where v.name is not null or
      (v.which = 'a' and
       t.namea is null and t.nameb is null and t.namec is null and t.named is null
      );

这可能是编写逻辑的最简单方法。

Unpivot?我没注意到你的答案,我现在就试试看。为了回答您的问题,在原始查询中,值永远不会为null,因此我只关心一条记录中的所有名称/值列是否为null,返回一条null记录,而不是每个名称/值对返回一条。我遇到问题是因为我有一个复杂的原始查询,这使得这有点困难。@T_Dejan。出于某种原因,最初的答案是针对SQL Server的(显然,我误读或忽略了问题上的标记)。我提供了一个与Oracle兼容的答案。你能看一下吗,我编辑了这个问题。我尝试使用子查询和交叉应用选项,但在实现时遇到了问题。这在甲骨文中可能吗?@T_Dejan。使用您的查询创建一个CTE(
带有t as(…)
),然后使用第一个版本带有
union all
@t_Dejan。你不接受这个答案有什么原因吗?您使用的是什么版本的Oracle?
select t.id, v.name, v.value
from t cross apply
     (values ('a', t.namea, t.valuea),
             ('b', t.nameb, t.valueb),
             ('c', t.namec, t.valuec),
             ('d', t.named, t.valued)
     ) v(which, name, value)
where v.name is not null or
      (v.which = 'a' and
       t.namea is null and t.nameb is null and t.namec is null and t.named is null
      );