web-dev-qa-db-fra.com

Tables de jointure et pivot SQL Server

J'ai deux tableaux avec des données

TABLEAU 1

    ---------------------------------------------------
    | SALEID | SOLDBY | SALEPRICE | MARGIN |   DATE   |
    |  1     |  'aa'  |  10,000   |   10   | 2013-1-1 |
    |  2     |  'bb'  |  25,000   |    5   | 2013-5-1 |

TABLEAU 2

    ---------------------------------------------------
    | SALEITEMID | SALEID | SALEPRICE | CATEGORY |
    |  1         |  1     |   6,000   | BOOKS    |
    |  2         |  1     |   4,000   | PRINTING |
    |  3         |  2     |   5,000   | BOOKS    |
    |  4         |  2     |   12,000  | PRINTING |
    |  5         |  2     |   8,000   | DVD      |

J'ai besoin d'une requête qui produira

TAB

    --------------------------------------------------------------------------------
    | SALEID | SOLDBY | SALEPRICE | MARGIN |   DATE   |  BOOKS  | PRINTING | DVD
    |  1     |  'aa'  |  10,000   |   10   | 2013-1-1 |  6,000  |  4,000   | 0
    |  2     |  'bb'  |  25,000   |    5   | 2013-5-1 |  5,000  | 12,000   | 8,000

Je suis assez nouveau dans le pivot et je ne sais pas si le pivot est le chemin à parcourir pour cela ou non.

25
Null Head

Cela devrait fonctionner:

WITH Sales AS (
   SELECT
      S.SaleID,
      S.SoldBy,
      S.SalePrice,
      S.Margin,
      S.Date,
      I.SalePrice,
      I.Category
   FROM
      dbo.Sale S
      INNER JOIN dbo.SaleItem I
         ON S.SaleID = I.SaleID
)
SELECT *
FROM
   Sales
   PIVOT (Max(SalePrice) FOR Category IN (Books, Printing, DVD)) P
;

Ou alternativement:

SELECT
   S.SaleID,
   S.SoldBy,
   S.SalePrice,
   S.Margin,
   S.Date,
   I.Books,
   I.Printing,
   I.DVD
FROM
   dbo.Sale S
   INNER JOIN (
      SELECT *
      FROM
         (SELECT SaleID, SalePrice, Category FROM dbo.SaleItem) I
         PIVOT (Max(SalePrice) FOR Category IN (Books, Printing, DVD)) P
   ) I ON S.SaleID = I.SaleID
;

Ceux-ci ont le même jeu de résultats et peuvent en fait être traités de la même manière par l'optimiseur de requête, mais peut-être pas. La grande différence entre en jeu lorsque vous commencez à mettre des conditions sur la table Sale: vous devez tester et voir quelle requête fonctionne mieux.

Puis-je suggérer, cependant, que vous fassiez le pivotement dans la couche de présentation? Si, par exemple, vous utilisez SSRS, il est assez facile d'utiliser un contrôle matriciel qui fera tout le pivotement pour vous. C'est mieux, car alors si vous ajoutez un nouveau Category, vous n'aurez pas à modifier tout votre code SQL!

Il existe un moyen de trouver dynamiquement les noms de colonnes à pivoter, mais cela implique un SQL dynamique. Je ne le recommande pas vraiment non plus, même si c'est possible.

Une autre façon dont pourrait fonctionner serait de prétraiter cette requête, c'est-à-dire de définir un déclencheur sur la table Category qui réécrit une vue à contenir toutes les catégories existantes qui existent. Cela résout beaucoup d'autres problèmes que j'ai mentionnés, mais encore une fois, il est préférable d'utiliser la couche de présentation.

Remarque: si vos noms de colonnes (qui étaient auparavant des valeurs) ont des espaces, sont des nombres ou commencent par un nombre, ou ne sont pas des identifiants valides, vous devez les citer entre crochets comme dans PIVOT (Max(Value) FOR CategoryId IN ([1], [2], [3], [4])) P. Vous pouvez également modifier les valeurs avant qu'elles n'atteignent la partie PIVOT de la requête pour ajouter des lettres ou supprimer des espaces, afin que la liste des colonnes n'ait pas besoin d'être échappée. Pour plus d'informations à ce sujet, consultez les règles relatives aux identificateurs dans SQL Server.

44
ErikE