Hoe kan ik gegevens ophalen uit gekoppelde tabellen?

Ik heb 3 tafels:

products table
--------------
id
name
...


categories table
----------------
id
name
...


product_categories table
------------------------
product_id
category_id

En voeg je bij deze vraag:

select p.*
from products p
join product_categories pc on pc.product_id = p.id
join categories c on pc.category_id = c.id

Deze query retourneert meerdere records van een product per categorie van dat product, maar ik wil slechts één product en meerdere categorieën van dat product ontvangen.

Dit is mijn output:

p.Id  p.name --> cat_id cat_name

1 product_1 --> 1 cat1
1 product_1 --> 3 cat3
1 product_1 --> 2 cat2
1 product_1 --> 6 cat6 
2 product_2 --> 5 cat5
2 product_2 --> 1 cat1 
.
.
.

En de gewenste output:

p.Id  p.name --> cat_id cat_name,cat_id cat_name,...

1 product_1 --> 1 cat1,3 cat3,2 cat2,6 cat6 
2 product_2 --> 5 cat5,1 cat1 
.
.
.

Hoe kan ik dat doen?

1
Ik begrijp dat, maar in plaats van een kolom te hebben voor elke categorie, zou je graag de productnaam willen retourneren en een andere kolom die een string bevat met alle categorieën voor dat product?
toegevoegd de auteur sr28, de bron
Ik begrijp dat, maar in plaats van een kolom te hebben voor elke categorie, zou je graag de productnaam willen retourneren en een andere kolom die een string bevat met alle categorieën voor dat product?
toegevoegd de auteur sr28, de bron
Ik begrijp dat, maar in plaats van een kolom te hebben voor elke categorie, zou je graag de productnaam willen retourneren en een andere kolom die een string bevat met alle categorieën voor dat product?
toegevoegd de auteur sr28, de bron
Zou je blij zijn met het retourneren van een string met alle categorieën, bijvoorbeeld "1 cat1, 3 cat3, 6 cat6"?
toegevoegd de auteur sr28, de bron
Zou je blij zijn met het retourneren van een string met alle categorieën, bijvoorbeeld "1 cat1, 3 cat3, 6 cat6"?
toegevoegd de auteur sr28, de bron
Zou je blij zijn met het retourneren van een string met alle categorieën, bijvoorbeeld "1 cat1, 3 cat3, 6 cat6"?
toegevoegd de auteur sr28, de bron
voeg een WHERE -clausule toe. WHERE p.id =
toegevoegd de auteur Felix Pamittan, de bron
voeg een WHERE -clausule toe. WHERE p.id =
toegevoegd de auteur Felix Pamittan, de bron
voeg een WHERE -clausule toe. WHERE p.id =
toegevoegd de auteur Felix Pamittan, de bron
SELECT c. * en gebruik een WHERE -clausule
toegevoegd de auteur ughai, de bron
SELECT c. * en gebruik een WHERE -clausule
toegevoegd de auteur ughai, de bron
SELECT c. * en gebruik een WHERE -clausule
toegevoegd de auteur ughai, de bron
Dus geef nu een tabelstructuur met voorbeeldgegevens (het beste om sql fiddle te maken)
toegevoegd de auteur Stanislovas Kalašnikovas, de bron
Lever uw uitvoer voor nu en de gewenste uitvoer.
toegevoegd de auteur Stanislovas Kalašnikovas, de bron
Lever uw uitvoer voor nu en de gewenste uitvoer.
toegevoegd de auteur Stanislovas Kalašnikovas, de bron
Lever uw uitvoer voor nu en de gewenste uitvoer.
toegevoegd de auteur Stanislovas Kalašnikovas, de bron
Dus geef nu een tabelstructuur met voorbeeldgegevens (het beste om sql fiddle te maken)
toegevoegd de auteur Stanislovas Kalašnikovas, de bron
welke ouptput je wilt, laat het hier zien. we zullen een beter begrip hebben
toegevoegd de auteur Ameya Deshpande, de bron
@AmeyaDeshpande Ik wil een resultaat als volgt: code 1 product_1 cat1, cat3, cat2, cat6 | 2 product_2 cat5, cat1 | ...
toegevoegd de auteur Mike, de bron
@ StanislovasKalašnikovas sqlfiddle
toegevoegd de auteur Mike, de bron
@ sr28 Alle categorieën voor een dat product.
toegevoegd de auteur Mike, de bron
@wewesthemenace Ik wil een resultaat zoals dit: code 1 product_1 cat1, cat3, cat2, cat6 | 2 product_2 cat5, cat1 | ...
toegevoegd de auteur Mike, de bron
@ StanislovasKalašnikovas Ik heb mijn vraag bewerkt.
toegevoegd de auteur Mike, de bron
@ StanislovasKalašnikovas Ik heb mijn vraag bewerkt.
toegevoegd de auteur Mike, de bron
@ StanislovasKalašnikovas Ik heb mijn vraag bewerkt.
toegevoegd de auteur Mike, de bron
@wewesthemenace Ik wil een resultaat zoals dit: code 1 product_1 cat1, cat3, cat2, cat6 | 2 product_2 cat5, cat1 | ...
toegevoegd de auteur Mike, de bron
@ughai Ik wil een resultaat zoals dit: code 1 product_1 cat1, cat3, cat2, cat6 | 2 product_2 cat5, cat1 | ...
toegevoegd de auteur Mike, de bron
@ughai Ik wil een resultaat zoals dit: code 1 product_1 cat1, cat3, cat2, cat6 | 2 product_2 cat5, cat1 | ...
toegevoegd de auteur Mike, de bron
@ sr28 Alle categorieën voor een dat product.
toegevoegd de auteur Mike, de bron
@ sr28 Alle categorieën voor een dat product.
toegevoegd de auteur Mike, de bron
@ sr28 Ja, maar ik wil de overtolligheid van productrecords niet: sqlfiddle
toegevoegd de auteur Mike, de bron
@ughai Ik wil een resultaat zoals dit: code 1 product_1 cat1, cat3, cat2, cat6 | 2 product_2 cat5, cat1 | ...
toegevoegd de auteur Mike, de bron
@AmeyaDeshpande Ik wil een resultaat als volgt: code 1 product_1 cat1, cat3, cat2, cat6 | 2 product_2 cat5, cat1 | ...
toegevoegd de auteur Mike, de bron
@AmeyaDeshpande Ik wil een resultaat als volgt: code 1 product_1 cat1, cat3, cat2, cat6 | 2 product_2 cat5, cat1 | ...
toegevoegd de auteur Mike, de bron
@ StanislovasKalašnikovas sqlfiddle
toegevoegd de auteur Mike, de bron
@ StanislovasKalašnikovas sqlfiddle
toegevoegd de auteur Mike, de bron
@wewesthemenace Ik wil een resultaat zoals dit: code 1 product_1 cat1, cat3, cat2, cat6 | 2 product_2 cat5, cat1 | ...
toegevoegd de auteur Mike, de bron
@ sr28 Ja, maar ik wil de overtolligheid van productrecords niet: sqlfiddle
toegevoegd de auteur Mike, de bron
@ sr28 Ja, maar ik wil de overtolligheid van productrecords niet: sqlfiddle
toegevoegd de auteur Mike, de bron

8 antwoord

U moet de WHERE -clausule toevoegen om de ID op te geven en in de geselecteerde clausule misschien dat u c. * wilt gebruiken in plaats van p. * om alle gegevens op te halen uit categorieën.

select p.name, c.*  
from products p
join product_categories pc on pc.product_id = p.id
join categories c on pc.category_id = c.id
where p.id = --smth
4
toegevoegd
OP heeft ook gegevens uit categorieën nodig
toegevoegd de auteur ughai, de bron
@Mij kunt u proberen selecteer p.name, c. * om de naam van het product te krijgen en alles uit categorieën, bewerkte antwoorden.
toegevoegd de auteur Stanislovas Kalašnikovas, de bron
@Stanislovas Kalašnikovas Ik wil een product en alle categorieën ervan
toegevoegd de auteur Mike, de bron

U moet de WHERE -clausule toevoegen om de ID op te geven en in de geselecteerde clausule misschien dat u c. * wilt gebruiken in plaats van p. * om alle gegevens op te halen uit categorieën.

select p.name, c.*  
from products p
join product_categories pc on pc.product_id = p.id
join categories c on pc.category_id = c.id
where p.id = --smth
4
toegevoegd
OP heeft ook gegevens uit categorieën nodig
toegevoegd de auteur ughai, de bron
@Mij kunt u proberen selecteer p.name, c. * om de naam van het product te krijgen en alles uit categorieën, bewerkte antwoorden.
toegevoegd de auteur Stanislovas Kalašnikovas, de bron
@Stanislovas Kalašnikovas Ik wil een product en alle categorieën ervan
toegevoegd de auteur Mike, de bron

U moet de WHERE -clausule toevoegen om de ID op te geven en in de geselecteerde clausule misschien dat u c. * wilt gebruiken in plaats van p. * om alle gegevens op te halen uit categorieën.

select p.name, c.*  
from products p
join product_categories pc on pc.product_id = p.id
join categories c on pc.category_id = c.id
where p.id = --smth
4
toegevoegd
OP heeft ook gegevens uit categorieën nodig
toegevoegd de auteur ughai, de bron
@Mij kunt u proberen selecteer p.name, c. * om de naam van het product te krijgen en alles uit categorieën, bewerkte antwoorden.
toegevoegd de auteur Stanislovas Kalašnikovas, de bron
@Stanislovas Kalašnikovas Ik wil een product en alle categorieën ervan
toegevoegd de auteur Mike, de bron
SELECT        Tbl_Emp.EMPId, Tbl_Customer.First_Name, Tbl_Mail_IDs.MailId
FROM          Tbl_Emp INNER JOIN
      Tbl_Mail_IDs ON Tbl_Emp.EMPId = Tbl_Mail_IDs.Id INNER     
JOIN
      Tbl_Customer ON Tbl_Mail_IDs.Id = Tbl_Customer.Customer_Id
1
toegevoegd
Over het algemeen vermijd alleen-antwoorden. Overweeg een -beschrijving toe te voegen die u helpt uw ​​code uit te leggen. Bedankt
toegevoegd de auteur MickyD, de bron
SELECT        Tbl_Emp.EMPId, Tbl_Customer.First_Name, Tbl_Mail_IDs.MailId
FROM          Tbl_Emp INNER JOIN
      Tbl_Mail_IDs ON Tbl_Emp.EMPId = Tbl_Mail_IDs.Id INNER     
JOIN
      Tbl_Customer ON Tbl_Mail_IDs.Id = Tbl_Customer.Customer_Id
1
toegevoegd
Over het algemeen vermijd alleen-antwoorden. Overweeg een -beschrijving toe te voegen die u helpt uw ​​code uit te leggen. Bedankt
toegevoegd de auteur MickyD, de bron
SELECT        Tbl_Emp.EMPId, Tbl_Customer.First_Name, Tbl_Mail_IDs.MailId
FROM          Tbl_Emp INNER JOIN
      Tbl_Mail_IDs ON Tbl_Emp.EMPId = Tbl_Mail_IDs.Id INNER     
JOIN
      Tbl_Customer ON Tbl_Mail_IDs.Id = Tbl_Customer.Customer_Id
1
toegevoegd
Over het algemeen vermijd alleen-antwoorden. Overweeg een -beschrijving toe te voegen die u helpt uw ​​code uit te leggen. Bedankt
toegevoegd de auteur MickyD, de bron

Als u de overtolligheid van de productrecords niet wilt, met andere woorden, u wilt alleen de categorie-informatie en niets anders, dan heeft u de join in de eerste plaats niet nodig voor de tabel met hoofdproducten (ervan uitgaande dat u de Product-ID).

U bent echter een probleem, tenzij u van plan bent om voor elke mogelijke categorie een kolom weer te geven en of het product het heeft of niet, dan moet u een work-around doen. Mijn voorkeur gaat uit naar het maken van een cursor die door elke rij loopt en de categorieën voor een bepaald product-ID in een enkele reeks trekt en deze reeks in een nieuwe tabel plaatst (product-ID, categorieën).

DECLARE @productId int
DECLARE @prevProductId int
SET @prevProductId = 0
DECLARE @cid int
DECLARE @cname nvarchar(255)
DECLARE @categoryList nvarchar(max)
SET @categoryList = ''

DECLARE @ProdCatTable TABLE
(
    ProductId int,
    Categories nvarchar(max)
)

DECLARE category_cursor CURSOR FOR
SELECT pc.product_id, c.id, c.name
FROM categories c
JOIN product_categories pc
ON pc.category_id = c.id
ORDER BY pc.product_id

OPEN category_cursor

FETCH NEXT FROM category_cursor
INTO @productId, @cid, @cname

WHILE @@FETCH_STATUS = 0
BEGIN
    IF @prevProductId = 0
    BEGIN
        SET @categoryList = @cid + ' ' + @cname
        SET @prevProductId = @productId
    END
    ELSE IF (@prevProductId <> @productId) AND @categoryList <> ''
         INSERT INTO @ProdCatTable (ProductId, Categories)
         VALUES (@prevProductId, @categoryList)
         SET @prevProductId = @ProductId
         SET @categoryList = ''
    ELSE
    BEGIN
        SET @categoryList = @categoryList + ', ' + @cid + ' ' + @cname
    END

    FETCH NEXT FROM category_cursor
    INTO @productId, @cid, @cname
END

CLOSE category_cursor
DEALLOCATE category_cursor

SELECT ProductId, Catgories
FROM @ProdCatTable

NOTE: This hasn't been tested, but I think it should work if you're happy to return a table with the product id as your identify and the categories as a string.

0
toegevoegd
@Mike - In navolging van de bovenstaande opmerking, is het niet waarschijnlijk dat dit in alle vormen een opgeruimde oplossing is. Als je misschien maar 10 categorieën had, zou het misschien beter zijn om de route te verlaten die in mijn tweede alinea wordt gesuggereerd, en die is nog steeds niet erg leuk, maar zou beter kunnen presteren.
toegevoegd de auteur sr28, de bron
Zoals ik al zei, ik heb het niet getest. Als je alleen alleen de tabellen leest, is een snel vooruit gerichte cursor misschien beter.
toegevoegd de auteur sr28, de bron
Bedankt voor je antwoord. is dit het beste en geoptimaliseerde antwoord voor dit scenario? Ik wil elk product met zijn categorieën tonen.
toegevoegd de auteur Mike, de bron

Als u de overtolligheid van de productrecords niet wilt, met andere woorden, u wilt alleen de categorie-informatie en niets anders, dan heeft u de join in de eerste plaats niet nodig voor de tabel met hoofdproducten (ervan uitgaande dat u de Product-ID).

U bent echter een probleem, tenzij u van plan bent om voor elke mogelijke categorie een kolom weer te geven en of het product het heeft of niet, dan moet u een work-around doen. Mijn voorkeur gaat uit naar het maken van een cursor die door elke rij loopt en de categorieën voor een bepaald product-ID in een enkele reeks trekt en deze reeks in een nieuwe tabel plaatst (product-ID, categorieën).

DECLARE @productId int
DECLARE @prevProductId int
SET @prevProductId = 0
DECLARE @cid int
DECLARE @cname nvarchar(255)
DECLARE @categoryList nvarchar(max)
SET @categoryList = ''

DECLARE @ProdCatTable TABLE
(
    ProductId int,
    Categories nvarchar(max)
)

DECLARE category_cursor CURSOR FOR
SELECT pc.product_id, c.id, c.name
FROM categories c
JOIN product_categories pc
ON pc.category_id = c.id
ORDER BY pc.product_id

OPEN category_cursor

FETCH NEXT FROM category_cursor
INTO @productId, @cid, @cname

WHILE @@FETCH_STATUS = 0
BEGIN
    IF @prevProductId = 0
    BEGIN
        SET @categoryList = @cid + ' ' + @cname
        SET @prevProductId = @productId
    END
    ELSE IF (@prevProductId <> @productId) AND @categoryList <> ''
         INSERT INTO @ProdCatTable (ProductId, Categories)
         VALUES (@prevProductId, @categoryList)
         SET @prevProductId = @ProductId
         SET @categoryList = ''
    ELSE
    BEGIN
        SET @categoryList = @categoryList + ', ' + @cid + ' ' + @cname
    END

    FETCH NEXT FROM category_cursor
    INTO @productId, @cid, @cname
END

CLOSE category_cursor
DEALLOCATE category_cursor

SELECT ProductId, Catgories
FROM @ProdCatTable

NOTE: This hasn't been tested, but I think it should work if you're happy to return a table with the product id as your identify and the categories as a string.

0
toegevoegd
@Mike - In navolging van de bovenstaande opmerking, is het niet waarschijnlijk dat dit in alle vormen een opgeruimde oplossing is. Als je misschien maar 10 categorieën had, zou het misschien beter zijn om de route te verlaten die in mijn tweede alinea wordt gesuggereerd, en die is nog steeds niet erg leuk, maar zou beter kunnen presteren.
toegevoegd de auteur sr28, de bron
Zoals ik al zei, ik heb het niet getest. Als je alleen alleen de tabellen leest, is een snel vooruit gerichte cursor misschien beter.
toegevoegd de auteur sr28, de bron
Bedankt voor je antwoord. is dit het beste en geoptimaliseerde antwoord voor dit scenario? Ik wil elk product met zijn categorieën tonen.
toegevoegd de auteur Mike, de bron