J'ai besoin d'un moyen de gérer le scénario suivant.
Rédigez une requête pour transformer l'ensemble de résultats suivant
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 );
... en celui-ci
ID|Location|Name |Value | __|________|_____|______| 0 | BL |NULL |NULL | __|________|_____|______| 1 | GT |x |y | __|________|_____|______| 1 | GT |s |z | __|________|_____|______| 2 | SZ |c |d | _|________|_____|______| 2 | SZ |e |f |
MODIFIER: J'ai décidé d'utiliser votre option d'application croisée, mais j'ai du mal à l'implémenter, Je vais coller ma requête d'origine avec les noms de table modifiés pour que Gordon ou quelqu'un d'autre puisse m'aider.
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 | __|________|_____|______|_____|______|_____|______|_____|______|
4 Réponses :
Utilisez simplement UNION
, comme ci-dessous:
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
Ou vous pouvez utiliser UNPIVOT
comme suit:
-- 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
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]; try this.
La réponse la plus simple dans Oracle est probablement:
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 );
Pour certains (raison probablement absurde), j'ai fourni la réponse ci-dessous en pensant que la question était étiquetée SQL Server. Oracle 12C prend en charge les jointures latérales, donc ce qui suit pourrait être adapté à la syntaxe Oracle.
Je laisse le reste de la réponse ici.
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);
I aime décomposer en utilisant cross apply
. Donc, le décompressé de base est:
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);
Vous voulez alors une condition que null
n'apparaisse qu'une seule fois si c'est tout le valeurs. Vous pouvez utiliser les fonctions de fenêtre pour cela:
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 );
Je ne sais pas si vous vous souciez simplement de savoir si nom
est NULL code > ou si vous voulez que
nom
et valeur
soient NULL
. L'une ou l'autre logique peut être mise en œuvre; on ne sait tout simplement pas ce que vous voulez.
EDIT:
Vous pouvez également le faire sans sous-requête:
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 ;
Ceci est probablement la manière la plus simple d'écrire la logique.
Je n'ai pas remarqué votre réponse, je vais essayer maintenant. Et pour répondre à votre question, dans la requête d'origine, VALUE ne sera jamais nulle, donc je me soucie seulement de savoir si toutes les colonnes NAME / VALUE d'un enregistrement sont nulles, pour renvoyer un enregistrement NULL et non celui de chaque paire NAME / VALUE. J'ai des problèmes à cause d'une requête originale complexe que j'ai, ce qui rend les choses un peu difficiles.
@T_Dejan. . . Pour une raison quelconque, la réponse originale était pour SQL Server (évidemment j'ai mal lu ou ignoré les balises sur la question). J'ai fourni une réponse compatible avec Oracle.
Pouvez-vous jeter un oeil, j'ai édité la question. J'ai essayé avec l'option de sous-requête et d'application croisée, mais j'ai du mal à l'implémenter. Est-ce possible dans Oracle?
@T_Dejan. . . Créez un CTE avec votre requête ( avec t comme (...)
), puis utilisez la première version avec union all
.
@T_Dejan. . . Y a-t-il une raison pour laquelle vous n'avez pas accepté la réponse? Quelle version d'Oracle utilisez-vous?
Annuler le pivot? oracle.com/technetwork/articles/sql/11g-pivot- 097235.html