2017-08-24 4 views
5

J'ai quatre tables: Documents, Articles, Articles et DocumentRelations. Dans Documents il y a trois types de documents, cette question ne concerne que deux d'entre eux: l'ordre et la facture. La facture est générée en fonction des commandes. La facture peut avoir plusieurs commandes et une commande peut avoir plusieurs factures. Commande et facture peuvent avoir plusieurs éléments. Table DocumentRelations contient les relations entre les commandes et les factures, quelle facture a été générée à partir de quelle commande/commande.Lignes multiplicatives SQL. Données de la même table l'une à côté de l'autre dans la sélection

Documents: 
ID | Name 
-- | -------- 
1 | O/2017/1 
2 | I/2017/1 
3 | O/2017/2 
4 | I/2017/2 
5 | O/2017/3 
6 | O/2017/4 
.. | ... 
99 | X/2017/1 

Ttems: 
ID | ArticleID | DocumentID | Quantity 
-- | --------- | ---------- | -------- 
1 | 1   | 1   | 12 
2 | 1   | 2   | 3 
3 | 2   | 3   | 41 
4 | 2   | 4   | 41 
5 | 1   | 4   | 59 
6 | 1   | 5   | 59 
7 | 3   | 6   | 7 

Articles: 
ID | Name 
-- | ---- 
1 | A 
2 | B 
3 | c 

DocumentRelations: 
OrderID | InvoiceID 
------- | --------- 
1  | 2 
3  | 4 
5  | 4 
8  | 9 
8  | 10 
8  | 11 

Scénario 1: ordre correspondant/s à la facture/s n'existe pas. La/les facture (s) correspondante (s) à la commande/s n'existe pas.

Scénario 2: La/les facture (s) correspondante (s) à la commande ne contient pas la même quantité de chaque article que la facture/s. La/les commande (s) correspondante (s) à facture (s) ne contient pas la même quantité de chaque article que commande/s.

Voici mon problème commence: Je dois obtenir la liste des articles avec des quantités dans chaque document sous une forme facilement comparable. Donc, identifiant de la commande, identifiant de la facture, nom de l'article, quantité dans la commande, quantité dans la facture.

OrderID | InvoiceID | ItemNameInOrder | QuantityInOrder | QuantityInInvoice 
------- | --------- | --------------- | --------------- | ----------------- 
1  | 2   | A    | 12    | 3 
3  | 4   | B    | 41    | 41 
5  | 4   | A    | 59    | 59 
6  | NULL  | C    | 7    | NULL 
NULL | 7   | B    | NULL   | 11 
8  | 9   | A    | 10    | 9 
8  | 10  | A    | 10    | 9 
8  | 11  | A    | 10    | 19 

Si la commande pour une facture spécifique n'existe pas, laisser la valeur null dans la colonne avec le nom et la quantité. Table DocumentRelations contient trois types de document, de sorte que les documents avec le troisième ne doivent pas apparaître.

Mon premier plan était de faire deux sélections retournant des colonnes dont j'ai seulement besoin, chacune pour le type de document. Puis, rejoignez-les en fonction des ID dans DocumentRelations. Mais cela multiple tout. Environ 3 fois plus que le résultat estimé.

SELECT O.ID, I.ID, O.ArticleName, O.Quantity, I.Quantity 
    FROM DocumentRelations R 
LEFT JOIN (SELECT D.ID, D.NumberString, I.Quantity, A.Name 
      FROM Documents D 
      JOIN Items I 
       ON D.ID = I.DocumentID 
      JOIN Articles A 
       ON I.ArticleID = A.ID 
      WHERE D.Name LIKE 'O/%') O 
     ON R.OrderID = O.ID 
LEFT JOIN (SELECT D.ID, , I.Quantity, A.Name 
      FROM Documents D 
      JOIN Items I 
       ON D.ID = I.DocumentID 
      JOIN Articles A 
       ON I.ArticleID = A.ID 
      WHERE D.Name LIKE 'I/%') I 
     ON R.InvoiceID = I.ID 

deuxième est similaire à première mais sans utiliser DocumentRelations à la fin. Créez deux sélections, une avec l'ID de la commande, le nom de l'article, la quantité de l'article et l'identifiant de la facture correspondante. La deuxième est la même mais pour les factures. Rejoignez-les avec une jointure externe complète basée sur la colonne avec l'ID du document correspondant, mais le résultat est le même.

SELECT O.ID, I.ID, O.ArticleName, O.Quantity, I.Quantity 
    FROM (SELECT D.ID, D.NumberString, I.Quantity, A.Name, R.InvoiceID 
      FROM Documents D 
      JOIN Items I 
      ON D.ID = I.DocumentID 
      JOIN Articles A 
      ON I.ArticleID = A.ID 
    LEFT JOIN DocumentRelations R 
      ON D.ID = R.OrderID 
     WHERE D.Name LIKE 'O/%') O 
FULL OUTER JOIN (
     SELECT D.ID, D.NumberString, I.Quantity, A.Name 
      FROM Documents D 
      JOIN Items I 
      ON D.ID = I.DocumentID 
      JOIN Articles A 
      ON I.ArticleID = A.ID 
     WHERE D.Name LIKE 'I/%') I 
    ON O.InvoiceID = I.ID 
+3

Voici comment la question devrait ressembler. Envisagez d'ajouter le schéma et les données de http://rextester.com pour obtenir une réponse rapide et précise. – lad2025

+1

il me faudra un certain temps pour le préparer. Merci du conseil. – Sonia

+0

Comment la première requête "Multiples tout"? Cela me semble correct. Veuillez publier les résultats que vous obtenez à partir de votre première requête avec vos exemples de données afin que nous puissions voir ce qui ne va pas. La deuxième requête est définitivement fausse. –

Répondre

1

J'aime le second - il vous suffit d'ajouter ArticleID à vos conditions et vous obtiendrez presque que vous voulez, à l'exception des noms manquants pour certaines chaînes. Et nous supposons que vous n'avez pas deux ou plusieurs lignes pour le même article dans un seul document:

SELECT O.ID, I.ID, O.ArticleName, O.Quantity, I.Quantity 
    FROM (SELECT D.ID, D.NumberString, I.Quantity, A.Name, R.InvoiceID, D.ArticleID 
      FROM Documents D 
      JOIN Items I 
      ON D.ID = I.DocumentID 
      JOIN Articles A 
      ON I.ArticleID = A.ID 
    LEFT JOIN DocumentRelations R 
      ON D.ID = R.OrderID 
     WHERE D.Name LIKE 'O/%') O 
FULL OUTER JOIN (
     SELECT D.ID, D.NumberString, I.Quantity, A.Name, D.ArticleID 
      FROM Documents D 
      JOIN Items I 
      ON D.ID = I.DocumentID 
      JOIN Articles A 
      ON I.ArticleID = A.ID 
     WHERE D.Name LIKE 'I/%') I 
      ON D.InvoiceID = I.ID 
      AND D.ArticleID = I.ArticleID 
+0

J'ai fait une erreur dans la dernière ligne de la deuxième requête, qui devrait être O au lieu de D. De toute façon, 'AND O.ArticleID = I.ArticleID' probablement résolu.Il donne les résultats les plus proches des estimations. Je vais faire quelques tests pour le confirmer. – Sonia