显示部分或完全缺少关联值的标题

时间:2017-03-30 14:08:01

标签: sql sql-server tsql stored-procedures

我在为以下场景编写SQL查询时遇到问题。我需要有人的帮助来编写查询。

我有以下表格7表:

1)标题

ID    Title                                                        Author         
-------------------------------------------------------------------------
1     The Hidden Language of Computer Hardware and Software   Charles Petzold
2     Paths, Dangers, Strategies                              Nick Bostrom
3     The Smart Girl's Guide to Privacy                       Violet Blue
4     Introduction to Algorithms                              Thomas H. Cormen
5     Machine Learning in Action                              Peter Harrington
...

2)主题

ID         Name
------------------------------------------
1          Science Fiction
2          Biography
3          Painting
...

3)主题

ID           Name
-----------------------------------
1            Science 
2            Technology
3            Music
4            Geography
...

4)成绩

ID            Name
------------------------------------
1             Grade 1
2             Grade 2
3             Grade 3
4             Grade 4
5             Grade 5
...

5)TitleThemeAssociation

TitleID         ThemeID
------------------------------------------
1               1
1               3
4               2
4               3
...

6)TitleSubjectAssociaton

TitleID          SubjectID
---------------------------------
1                1
1                3
2                1
2                3 
4                1
4                2  
...

7)TitleGradeAssociaton

TitleID              GradeID
1                    1
1                    2
1                    3
2                    1
2                    2
...

我需要编写一个查询来仅显示缺少三个值(主题,主题和成绩)中的任何一个的标题,或者不完全分配值。如果分配了所有三个值(主题,主题,成绩),我不应该显示标题。在上面的数据集中,由于 TitleID 1 具有所有三个值,因此它不应出现在列表中。 TitleID 2 只分配了主题和成绩,但没有主题,所以它应该显示在输出中。如果标题有多个值列出标题,那么应该用逗号(,)分隔符联系它们。

因此上述数据集的最终输出应如下所示:

输出:

Title ID      Title                      Theme        Subject           Grade
-------------------------------------------------------------------------------------------
2      Paths, Dangers, Strategies          -          Science, Music    Grade 1, Grade 2
3      The Smart Girl's Guide to Privacy   -           -                   -
4      Introduction to Algorithms         Biography, Painting    Science, Technology    -
5      Machine Learning in Action          -              -              -

2 个答案:

答案 0 :(得分:1)

你问的问题基本上有两个。第一个是如何在ThemeSubjectGrade丢失时进行过滤。另一个是询问如何将这些项目连接成逗号分隔的列表。

以下查询应该是您要查找的内容:

Select  Distinct
        T.Id As [Title ID],
        T.Title,
        H.Theme,
        S.Subject,
        G.Grade
From    Titles  T
Outer Apply
(
    Select  Stuff(( Select ', ' + Name 
                    From    Themes                  H
                    Join    TitleThemeAssociation   TH  On  H.Id = TH.ThemeId
                    Where   TH.TitleId = T.Id 
                    For Xml Path('')), 1, 2, '') As Theme
    From    Themes
) H
Outer Apply
(
    Select  Stuff(( Select ', ' + Name 
                    From    Subjects                S
                    Join    TitleSubjectAssociaton  TS  On  S.Id = TS.SubjectId
                    Where   TS.TitleId = T.Id 
                    For Xml Path('')), 1, 2, '') As Subject
    From    Subjects
) S
Outer Apply
(
    Select  Stuff(( Select ', ' + Name 
                    From    Grades                  G
                    Join    TitleGradeAssociaton    TG  On  G.Id = TG.GradeId
                    Where   TG.TitleId = T.Id 
                    For Xml Path('')), 1, 2, '') As Grade
    From    Grades
) G
Where   H.Theme Is Null
Or      S.Subject Is Null
Or      G.Grade Is Null

答案 1 :(得分:1)

希望这有助于。

;WITH cte_Titles (ID,Title,Author)   AS     
(
SELECT 1,'The Hidden Language of Computer Hardware and Software','Charles Petzold' UNION ALL
SELECT 2,'Paths, Dangers, Strategies','Nick Bostrom' UNION ALL
SELECT 3,'The Smart Girls Guide to Privacy','Violet Blue' UNION ALL
SELECT 4,'Introduction to Algorithms','Thomas H. Cormen' UNION ALL
SELECT 5,'Machine Learning in Action','Peter Harrington'
),cte_Themes(ID,Name) AS
(
SELECT 1,'Science Fiction' UNION ALL
SELECT 2,'Biography' UNION ALL
SELECT 3,'Painting'
),cte_Subjects(ID,Name) AS
(
SELECT 1,'Science' UNION ALL
SELECT 2,'Technology' UNION ALL
SELECT 3,'Music' UNION ALL
SELECT 4,'Geography'
),cte_Grades(ID,Name) AS
(
SELECT 1,'Grade 1' UNION ALL
SELECT 2,'Grade 2' UNION ALL
SELECT 3,'Grade 3' UNION ALL
SELECT 4,'Grade 4' UNION ALL
SELECT 5,'Grade 5'
),cte_TitleThemeAssociation(TitleID,ThemeID) AS
(
SELECT 1,1 UNION ALL
SELECT 1,3 UNION ALL
SELECT 4,2 UNION ALL
SELECT 4,3
),cte_TitleSubjectAssociaton(TitleID,SubjectID) AS
(
SELECT 1, 1 UNION ALL
SELECT 1, 3 UNION ALL
SELECT 2, 1 UNION ALL
SELECT 2, 3 UNION ALL
SELECT 4, 1 UNION ALL
SELECT 4, 2
),cte_TitleGradeAssociaton(TitleID,GradeID) AS
(
SELECT 1, 1 UNION ALL
SELECT 1, 2 UNION ALL
SELECT 1, 3 UNION ALL
SELECT 2, 1 UNION ALL
SELECT 2, 2
)
,cte_ResultSet AS
(
SELECT DISTINCT t.ID AS TitleID,
    t.Title,
    th.NAME AS Theme,
    s.NAME AS Subject,
    g.NAME AS Grade
FROM cte_Titles t
LEFT JOIN cte_TitleThemeAssociation tta
    ON t.ID = tta.TitleID
LEFT JOIN cte_Themes th
    ON tta.ThemeID = th.ID
LEFT JOIN cte_TitleSubjectAssociaton tsa
    ON tsa.TitleID = t.ID
LEFT JOIN cte_Subjects s
    ON tsa.SubjectID = s.ID
LEFT JOIN cte_TitleGradeAssociaton tga
    ON tga.TitleID = t.ID
LEFT JOIN cte_Grades g
    ON g.ID = tga.GradeID
)
SELECT DISTINCT Title
                , STUFF((SELECT DISTINCT ',' + SUB.Theme AS [text()]
                        FROM cte_ResultSet SUB
                        WHERE SUB.TitleID = CAT.TitleID
                        FOR XML PATH('')
                        ), 1, 1, '' ) AS Theme
                , STUFF((SELECT DISTINCT ',' + SUB.Subject AS [text()]
                        FROM cte_ResultSet SUB
                        WHERE SUB.TitleID = CAT.TitleID
                        FOR XML PATH('')
                        ), 1, 1, '' ) AS Subject
                , STUFF((SELECT DISTINCT ',' + SUB.Grade AS [text()]
                        FROM cte_ResultSet SUB
                        WHERE SUB.TitleID = CAT.TitleID
                        FOR XML PATH('')
                        ), 1, 1, '' ) AS Grade
FROM cte_ResultSet CAT