Как вернуть одну запись, если все столбцы возвращают нуль или возвращают только ненулевые столбцы - PullRequest
1 голос
/ 16 мая 2019

Мне нужен способ обработки следующего сценария.

Напишите запрос для преобразования следующего набора результатов

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     |
  • Для записей со всеми пустыми столбцами «Имя / Значение» Мне не нужны четыре записи в результирующей таблице, мне нужна только одна.
  • Для записей сболее одной пары NON-NULL имя / значение. Я хочу, чтобы они отображались как отдельные записи полученной таблицы, а пары NULL имя / значение игнорируются.
  • Если, например, NameA не равно NULL, а ValueA равно NULL, оно отбрасывается изитоговая таблица, в соответствии с исходным сценарием.

РЕДАКТИРОВАТЬ: Я решил использовать опцию перекрестного применения, но у меня возникли проблемы с ее реализацией, я вставлю свой исходный запрос с измененными именами таблиц, чтобы Гордон или кто-то ещеможет помочь.

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
      );

Ответы [ 4 ]

2 голосов
/ 16 мая 2019

Или вы можете использовать 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
1 голос
/ 16 мая 2019

Самый простой ответ в 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.Oracle 12C поддерживает боковые объединения, поэтому приведенный ниже текст может быть адаптирован к синтаксису 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

      );

Мне нравится отключать, используя cross apply,Таким образом, основной разворот:

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
      );

Это, вероятно, самый простой способ написать логику.

0 голосов
/ 16 мая 2019
declare @tempTbl table ([ID] int, [Location] nvarchar(10), [Name] nvarchar(10), [Value] nvarchar(10));
insert into  @tempTbl 
 select  [ID],[Location],[Name], [Value] From
(
SELECT [ID],[Location],[NameA] as [Name],[ValueA] as [Value] FROM [dbo].[LocationTbl]
    UNION 
    SELECT [ID],[Location],[NameB],[ValueB] FROM [dbo].[LocationTbl]
    UNION 
    SELECT [ID],[Location],[NameC],[ValueC] FROM [dbo].[LocationTbl]
    UNION 
    SELECT [ID],[Location],[NameD],[ValueD] FROM [dbo].[LocationTbl]
) as X
where [Name] is not null AND [Value] is not null
select * from @tempTbl
UNION
SELECT [ID], [Location], Null as [Name], Null as [Value]
FROM [dbo].[LocationTbl]
WHERE  [Location] not in (select [Location] from @tempTbl)
order by [ID];

попробуйте это.

0 голосов
/ 16 мая 2019

Просто используйте UNION, как показано ниже:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...