web-dev-qa-db-fra.com

Obtenez la valeur de la première ligne de la troisième table tout en joignant 3 tables mssql

Je suis nouveau sur mssql .ici, j'ai besoin d'obtenir des données à l'aide de jointures entre trois tables.

En-tête jointure Lignes jointure Images -> Résultat

Tableau d'en-tête:

enter image description here

Tableau des lignes:

enter image description here

Pour chaque enregistrement d'en-tête, nous pouvons avoir plusieurs éléments de campagne.

Tableau des images:

enter image description here

Chaque image aura une image unique ou plusieurs images. Besoin d'obtenir 1 URL d'image dans la liste des éléments pour l'enregistrement d'en-tête.

Ensemble de résultats:

enter image description here

Requete :

SELECT HT.O_ID,
       HT.Type,
       HT.Total,
       IM.Image 

FROM HEADER_TABLE HT 

JOIN LINE_ITEM_TABLE LIT 
ON LIT.O_ID = HT.O_ID 

JOIN IMAGE_TABLE IT 
ON IT.IMAGE = LIT.ITEM_ID 

WHERE IT.SECTION = 'Retail'

Cette requête renvoie plusieurs lignes. Mais j'ai besoin d'une ligne unique pour chaque enregistrement d'en-tête.

Quelqu'un peut-il m'aider à réparer.

4
Zhu

Vous pouvez utiliser CROSS APPLY à SELECT juste le TOP 1 image de chaque en-tête particulier. APPLY est similaire à une fonction que vous pouvez créer "en déplacement" qui relie des colonnes ou des expressions de l'extérieur à ses filtres ou jointures.

SELECT
    -- Header columns:
    HT.O_ID,
    HT.Type,
    HT.Total,

    -- Columns from the CROSS APPLY result
    I.Image
FROM 
    HEADER_TABLE HT 
    CROSS APPLY (
        SELECT TOP 1 -- Just retrieve 1 row (for each HT row)
            IT.IMAGE
        FROM
            LINE_ITEM_TABLE LIT
            INNER JOIN IMAGE_TABLE IT ON IT.ITEM_ID = LIT.ITEM_ID
        WHERE
            LIT.O_ID = HT.O_ID AND  -- Link the outmost header "HT" record to it's lines "LIT"
            IT.SECTION = 'Retail') AS I

Vous pouvez ajouter un ORDER BY à l'intérieur de CROSS APPLY pour déterminer quelle image sera sélectionnée. Vous pouvez également modifier le CROSS APPLY à OUTER APPLY si vous souhaitez que les lignes d'en-tête s'affichent même en l'absence d'enregistrement correspondant provenant de l'opérateur APPLY (la colonne IMAGE sera NULL).

5
EzLo

Mais j'ai besoin d'une ligne unique pour chaque enregistrement d'en-tête.

Pour moi, il n'est pas clair si vous voulez dire un enregistrement unique par HT.O_ID ou aucun enregistrement en double concernant les quatre colonnes renvoyées.

S'il s'agit de ce dernier, ajoutez le mot clé DISTINCT à votre requête (et ajoutez les noms de schéma).

 SELECT DISTINCT HT.O_ID,
           HT.Type,
           HT.Total,
           IT.Image 

    FROM dbo.HEADER_TABLE HT 
    JOIN dbo.LINE_ITEM_TABLE LIT 
    ON LIT.O_ID = HT.O_ID 
    JOIN dbo.IMAGE_TABLE IT 
    ON IT.Item_ID = LIT.ITEM_ID 
    WHERE IT.SECTION = 'Retail';

Résultat

O_ID    Type    Total   Image
1001    Online  $10 URL

Si cela ne le résout pas

Ensuite, vous devez regrouper les valeurs dans le Header_Table Et décidez quelle Image vous devez conserver, faites-la concaténer, ....

SELECT HT.O_ID,
       HT.Type,
       HT.Total,
       MAX(IT.Image) as MaxURL

FROM dbo.HEADER_TABLE HT 
JOIN dbo.LINE_ITEM_TABLE LIT 
ON LIT.O_ID = HT.O_ID 
JOIN dbo.IMAGE_TABLE IT 
ON IT.Item_ID = LIT.ITEM_ID 
WHERE IT.SECTION = 'Retail'
GROUP BY HT.O_ID,HT.Type,HT.Total;

Données de test

CREATE TABLE dbo.HEADER_TABLE(O_ID int,Type varchar(100),Total varchar(10))
INSERT INTO dbo.HEADER_TABLE(O_ID,Type,Total)
VALUES  (1001,'Online','$10');

CREATE TABLE dbo.LINE_ITEM_TABLE(ID int,O_ID int,Item_ID varchar(4),Line_Total varchar(10));
INSERT INTO dbo.LINE_ITEM_TABLE(ID,O_ID,Item_ID,Line_Total)
VALUES  (1,1001,'P001','$2'),
        (2,1001,'P002','$2'),
        (3,1001,'P003','$2'),
        (4,1001,'P004','$2'),
        (5,1001,'P005','$2');


CREATE TABLE dbo.IMAGE_TABLE(Item_ID varchar(10),Image varchar(100),Section varchar(10))
INSERT INTO dbo.IMAGE_TABLE 
VALUES  ('P001','URL','Retail'),
        ('P002','URL','Retail'),
        ('P003','URL','Stock'),
        ('P004','URL','Retail'),
        ('P005','URL','Retail');
3
Randi Vertongen