web-dev-qa-db-fra.com

Comment faire pivoter dynamiquement avec la date comme colonne

J'ai un tableau avec les identifiants et les noms des produits, et un autre tableau avec le stock de ces produits à certaines dates. Tel que Item1 eu 6 stock sur 1-1-2014 et 8 stock sur 2-1-2014. J'essaie de les afficher dans une procédure stockée afin qu'elle ressemble à un calendrier, affichant toutes les dates d'un mois et le stock disponible dans les cellules. Quelle est la meilleure façon de le montrer?

Par exemple:

Name  | 1-1-2014 | 2-1-2014 | 3-1-2014 | 4-1-2014
Item1 |     6    |     8    |          |    6
Item2 |          |     2    |     1    |

Tableaux originaux - Noms

 ID |   Name 
  1 |  Item1
  2 |  Item2

Tableaux originaux - Stockdates

 ID | NameID  | Stock |    Date 
  1 |    1    |   8   |  2-1-2014    
  2 |    2    |   2   |  4-1-2014 
11
Craphex

Voici votre exemple de table

SELECT * INTO #Names
FROM
(
SELECT 1 ID,'ITEM1' NAME 
UNION ALL
SELECT 2 ID,'ITEM2' NAME 
)TAB

SELECT * INTO #Stockdates
FROM
(      
SELECT 1 ID,1 NAMEID,8 STOCK,'2-1-2014 ' [DATE]
UNION ALL
SELECT 2 ID,2 NAMEID,2 STOCK,'4-1-2014 ' [DATE]
)TAB

Placer les données de jointure dans une table temporaire

SELECT N.NAME,S.[DATE],S.STOCK 
INTO #TABLE
FROM #NAMES N
JOIN #Stockdates S ON N.ID=S.NAMEID

Obtenez les colonnes pour pivot

DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + CONVERT(NVARCHAR, [DATE], 106) + ']', 
               '[' + CONVERT(NVARCHAR, [DATE], 106) + ']')
               FROM    (SELECT DISTINCT [DATE] FROM #TABLE) PV  
               ORDER BY [DATE]

Maintenant, faites-le pivoter

DECLARE @query NVARCHAR(MAX)
SET @query = '           
              SELECT * FROM 
             (
                 SELECT * FROM #TABLE
             ) x
             PIVOT 
             (
                 SUM(STOCK)
                 FOR [DATE] IN (' + @cols + ')
            ) p      

            '     
EXEC SP_EXECUTESQL @query

Et votre résultat est là

enter image description here

16
Sarath Avanavu

Étape 1 - Combler les lacunes (peut-être pas nécessaire)

Si votre tableau des stocks ne contient pas de stock de tous les jours pour chaque produit, vous devez obtenir toutes les dates d'un mois ailleurs. Vous pouvez les générer avec un CTE récursif: (les déclarations de variables sont omises)

with dates as
(
   select @startdate as [date]
   union ALL
   select   [date] + 1 
   from dates
   where    [date] < @enddate
)
select  @strDays = COALESCE(@strDays + ', ['+ convert(varchar(8), [date],112) + ']', '['+ convert(varchar(8), [date],112) + ']') 
from    dates;

Vous pouvez utiliser votre format de date préféré, mais il est important de le conserver dans toutes les requêtes.

Étape 2 - Apportez les données sous une forme normale. Vous pouvez choisir de le stocker dans une table temporaire ou vous pouvez utiliser à nouveau un CTE et combiner cette étape avec l'étape 3.

Joignez dates (par le haut) avec products (complet) et avec stock (gauche) pour obtenir un tableau comme celui-ci:

date
product_id    
items

Pour les produits et les dates où le stock n'est pas disponible, vous affichez 0. isnull fera l'affaire. Assurez-vous que la colonne date est convertie en varchar dans le même format que dans CTE ci-dessus.

Étape 3 - faites pivoter le tableau (obtenu à l'étape 2) par la colonne date dans une requête dynamique.

Je peux vous donner plus de détails mais pas pour le moment. Vous pouvez voir quelque chose de similaire dans une autre réponse: répartir des valeurs distinctes sur différentes colonnes

2
B0Andrew