2017-10-10 4 views
1

Ceci est ma requête de sélection régulière:manière correcte de convertir les lignes à colonnes de requêtes SQL

SELECT [category], [price], [company] 
FROM [prices] 
INNER JOIN [company] AS [co] ON [co].[company] = [pr].[company] 
WHERE [co].[id] IN (1,2,3); 

Le résultat est:

category | price | company 
---------+-------+------------- 
Srv  | 1200 | CoA 
Srv  | 2800 | CoB 
EQ  | 5400 | CoA 
Deduc | 400 | CoA 
Deduc | 150 | CoB 

Et je besoin de ce résultat:

PriceASrv | PriceBSrv | PriceAEQ | PriceBEQ | PriceADeduc | PriceBDeduc 
-----------+-----------+----------+----------+-------------+------------- 
1200  | 2800  | 5400  | NULL  | 400   | 150 

Il me semble que j'ai besoin de deux fois PIVOT, ai-je raison? Est-ce que quelqu'un a une idée?

+1

Avez-vous un nombre fixe de colonnes ou est-il dynamique? –

+0

vous n'avez pas besoin de pivoter deux fois, mais comme vous le voyez dans les exemples ci-dessous, vous devez concaténer les valeurs 'company' et' category'. Il semble également que vous ayez besoin de toutes les catégories et de toutes les sociétés, lorsque le résultat est manquant. Avez-vous une table 'company' avec une ligne par' company' et une table 'category' avec une ligne par' category'? – Beth

+0

Le langage SQL ** vraiment ** doit être capable de savoir combien de colonnes et quel type à la compilation, avant que la requête ne s'exécute réellement sur n'importe quelle donnée. Si vous ne pouvez pas faire cela, vous devrez faire votre pivot en deux étapes via SQL dynamique (où la première étape détermine la réponse à cette question "combien de colonnes") ou faites votre pivot dans le code client. –

Répondre

1

Non, vous n'avez pas besoin de faire pivoter deux fois, mais vous pouvez avoir besoin d'une requête dynamique si:

  1. Il peut y avoir plus de deux entreprises, OU
  2. Vos noms d'entreprise peuvent modifier ou
  3. Vos catégories peuvent changer.

Si ces trois conditions sont toutes fausses, ou l'autre des requêtes suivantes fonctionnerait:

DECLARE @T TABLE (Category VARCHAR(10), Price INT, Company CHAR(3)); 
INSERT @T VALUES 
    ('Srv', 1200, 'CoA'), 
    ('Srv', 2800, 'CoB'), 
    ('EQ', 5400, 'CoA'), 
    ('Deduc', 400, 'CoA'), 
    ('Deduc', 150, 'CoB'); 

-- With PIVOT 
SELECT * 
FROM (
    SELECT CatCom = 'Price' + RIGHT(Company, 1) + Category, 
      Price 
    FROM @T) AS T 
PIVOT (MAX(Price) FOR CatCom IN ([PriceASrv], [PriceBSrv], [PriceAEQ], [PriceBEQ], [PriceADeduc], [PriceBDeduc])) AS P 

-- With CASE aggregation 
SELECT PriceASrv = MAX(CASE WHEN Category = 'Srv' AND Company = 'CoA' THEN Price END), 
     PriceBSrv = MAX(CASE WHEN Category = 'Srv' AND Company = 'CoB' THEN Price END), 
     PriceAEQ = MAX(CASE WHEN Category = 'EQ' AND Company = 'CoA' THEN Price END), 
     PriceBEQ = MAX(CASE WHEN Category = 'EQ' AND Company = 'CoB' THEN Price END), 
     PriceADeduc = MAX(CASE WHEN Category = 'Deduc' AND Company = 'CoA' THEN Price END), 
     PriceBDeduc = MAX(CASE WHEN Category = 'Deduc' AND Company = 'CoB' THEN Price END) 
FROM @T; 

Si l'une des trois conditions sont vraies, alors vous pouvez avoir besoin d'une requête dynamique (qui serait essentiellement une modification de l'une des requêtes ci-dessus pour répondre à vos besoins).

1

Non, vous n'avez pas besoin de PIVOT deux fois. Voir la requête ci-dessous. Vous pouvez convertir en pivot dynamique si vous ne connaissez pas le nombre d'entreprises peuvent être présentes

Select * from 
(
Select 
    [data]='Price' + RIGHT([company],1) +[category] , 
    [price] 
FROM [prices] 
INNER JOIN [company] as [co] On [co].[company] = [pr].[company] 
WHERE [co].[id] In (1,2,3))src 
PIVOT 
( 
MAX([price]) FOR [data] in (PriceASrv,PriceBSrv,PriceAEQ,PriceBEQ,PriceADeduc,PriceBDeduc) 
)p 

see working demo

+0

compte tenu de son résultat 'NULL', je pense qu'il aura besoin d'un' LEFT OUTER JOIN' au lieu de 'INNER' – Beth

+0

En fait, c'est un peu plus compliqué, comme il a besoin de toutes les «catégories» de «cross joint» avec toutes les «sociétés», puis de «left outer join» avec des «prix» connexes. – Beth

+1

@Beth J'ai créé une démo et j'ai rétabli mon changement. Cette INNER JOIN fonctionnera – DhruvJoshi