Search code examples
sqlsql-servergroup-concatsql-server-group-concat

T-SQL - Concatenation of names on TWO tables/orphans


I'm prepared to be crucified for asking my first question on SO and what is a potentially duplicate question, but I cannot find it for the life of me.

I have three tables, a product table, a linking table, and a child table with names. Preloaded on SQLFiddle >> if I still have your attention.

CREATE TABLE Product (iProductID int NOT NULL PRIMARY KEY
                    , sProductName varchar(50) NOT NULL
                    , iPartGroupID int NOT NULL)
INSERT INTO Product VALUES
(10001, 'Avionic Tackle', '1'),
(10002, 'Eigenspout', '2'),
(10003, 'Impulse Polycatalyst', '3'),
(10004, 'O-webbing', '2'),
(10005, 'Ultraservo', '3'),
(10006, 'Yttrium Coil', '5')

CREATE TABLE PartGroup (iPartGroupID int NOT NULL
                      , iChildID int NOT NULL)
INSERT INTO PartGroup VALUES
(1, 1),
(2, 2),
(3, 1),
(3, 2),
(3, 3),
(3, 4),
(4, 5),
(4, 6),
(5, 1)

CREATE TABLE PartNames (iChildID int NOT NULL PRIMARY KEY
                      , sPartNameText varchar(50) NOT NULL)
INSERT INTO PartNames VALUES
(1, 'Bulbcap Lube'),
(2, 'Chromium Deltaquartz'),
(3, 'Dilation Gyrosphere'),
(4, 'Fliphose'),
(5, 'G-tightener Bypass'),
(6, 'Heisenberg Shuttle')

I am trying to find out how to list all the part groups (that may or may not belong to a product), and translate their child names. That is, how do I use only the linking table and child name table to list all the translated elements of the linking table. I am trying to find orphans.

I have two queries:

SELECT P.iPartGroupID
    ,STUFF(
        (SELECT
            CONCAT(', ', PN.sPartNameText)
            FROM PartGroup PG
            INNER JOIN PartNames PN ON PN.iChildID = PG.iChildID
         WHERE PG.iPartGroupID = P.iPartGroupID
         FOR XML PATH(''), TYPE
        ).value('.', 'VARCHAR(MAX)')
        , 1, 2, ''
        ) AS [Child Elements]
FROM Product P
GROUP BY P.iPartGroupID

This lists all the part groups that belong to a product, and their child elements by name. iPartGroupID = 4 is not here.

I also have:

SELECT PG.iPartGroupID
    ,STUFF(
        (SELECT
            CONCAT(', ', PGList.iChildID)
            FROM PartGroup PGList
            WHERE PGList.iPartGroupID = PG.iPartGroupID
            FOR XML PATH(''), TYPE
        ).value('.', 'VARCHAR(MAX)')
        , 1, 2, ''
        ) AS [Child Elements]
FROM PartGroup PG
GROUP BY PG.iPartGroupID

This lists all the part groups, and their child elements by code. iPartGroupID = 4 is covered here, but the names aren't translated.

What query can I use to list the orphan part groups (and also the orphan parts):

 4     G-tightener Bypass, Heisenberg Shuttle

Ideally it is included in a list of all the other part groups, but if not, I can union the results.

Every other SO question I've looked up uses either 3 tables, or only 1 table, self joining with aliases. Does anyone have any ideas?

No XML in the part names, no particular preference for CONCAT or SELECT '+'.

I would link to other posts, but I can't without points :(


Solution

  • I'm not entirely sure what do you mean, exactly, when you use the word "translate". And your required output seems to contradict your sample data (if I'm not lost something).

    Nevertheless, try this query, maybe it's what you need:

    select sq.iPartGroupID, cast((
        select pn.sPartNameText + ',' as [data()] from @PartNames pn
            inner join @PartGroup p on pn.iChildID = p.iChildID
        where p.iPartGroupID = sq.iPartGroupID
        order by pn.iChildID
        for xml path('')
        ) as varchar(max)) as [GroupList]
    from (select distinct pg.iPartGroupID from @PartGroup pg) sq
        left join @Product pr on sq.iPartGroupID = pr.iPartGroupID
    where pr.iProductID is null;