SQL:联接3个表并在子查询中显示2个表中的所有数据

时间:2018-06-19 20:48:24

标签: sql sql-server join

我正在尝试联接三个表,并显示子查询中列出的两个表中的所有相关数据,以获取足够的数据,以便以后可以执行数据透视。

下面列出的是我正在使用的3个表的示例。

“ FileTable”:

select thread_starter, count(*)
from ./file.csv
group by thread_starter
order by 2 desc;

“ TagTable”:

---------------------
|FileTable          |
---------------------
| Id | Name         |
---------------------
| 1  |  File1.docx  |
| 2  |  File2.xlsx  |
| 3  |  File3.pdf   |
---------------------

“ TagValueTable”:

---------------
|TagTable     |
---------------
| Id | Name   |
---------------
| 1  |  Tag1  |
| 2  |  Tag2  |
| 3  |  Tag3  |
| 4  |  Tag4  |
| 5  |  Tag5  |
| 6  |  Tag6  |
---------------

我正在尝试编写一个查询,该查询将向我显示文件,并提供所有可用标签以及包含这些文件的标签值的所有可用标签。

我编写了以下查询,但是如果“ TagValue”表中有一个值,它只会显示文件和标签。

------------------------------------
|TagValueTable                     |
------------------------------------
|FileId | TagId | Value            |
------------------------------------
| 1     |  1    |  file1tag1value  |
| 1     |  2    |  file1tag2value  |
| 1     |  4    |  file1tag4value  |
| 2     |  1    |  file2tag1value  |
| 2     |  4    |  file2tag4value  |
------------------------------------

我希望结果显示如下。

SELECT 
    f.Id AS 'FileId', f.[Name] AS 'FileName', 
    t.[Name] AS 'TagName',
    tv.[Value] AS 'TagValue'
FROM 
    [FileTable] f
JOIN 
    TagValueTable tv ON tv.FileId = ISNULL(f.Id, tv.FileId)
JOIN 
    TagTable t ON t.Id = ISNULL(tv.TagId, t.Id)
ORDER BY
    f.Id

查询需要显示所有文件的所有可用标签及其标签值。如果文件没有标签值,则应为null。我确信可能有更好的设计,但是我必须处理现有数据,因此我无法进行更改。

我尝试使用不同的联接以多种不同方式重写上述查询,但似乎无法正常工作。另外,我也在视图中执行此操作,因此无法使用存储过程。

感谢您的帮助...

谢谢

罗伯特

3 个答案:

答案 0 :(得分:3)

您可以在此处使用CROSS JOIN和OUTER JOIN代替INNER JOIN。

SELECT 
    f.Id as FileID,
    f.Name AS FileName,
    t.Name AS TagName,
    tv.Value AS TagValue
FROM FileTable f
CROSS JOIN TagTable t
LEFT JOIN TagValueTable tv ON tv.FileId = f.Id
                           AND tv.TagId = t.Id

CROSS JOIN将为您提供FileTable和TagTable的所有排列。 LEFT JOIN将引入TagValueTable中的标记值,同时保留先前JOIN的所有结果。内部联接(例如您正在使用的联接)将仅返回两个表中匹配的记录。

这是一个有关INNER和OUTER连接之间区别的问题。
What is the difference between "INNER JOIN" and "OUTER JOIN"?

答案 1 :(得分:0)

select x.FileId, x.FileName, x.TagName, tv.Value
from (
    select f.id FileId, f.name FileName, t.id TagId, t.Name TagName
    from FileTable f, TagTable t
    ) x
    left join TagValueTable tv on x.FileId = tv.FileId and x.TagId = tv.TagId

答案 2 :(得分:0)

由于您需要每个文件的每个标签,因此需要先CROSS APPLY个标签,然后LEFT OUTER JOIN个链接表才能获得与该文件关联的Value和标签。

设置

CREATE TABLE FileTable ( Id int, Name varchar(20) ) ;

INSERT INTO FileTable (Id, Name)
VALUES ( 1, 'File1.docx' ), ( 2, 'File2.xlsx' ), ( 3, 'File3.pdf' ) ;

CREATE TABLE TagTable ( Id int, Name varchar(20) ) ;

INSERT INTO TagTable (Id, Name)
VALUES 
    ( 1, 'Tag1' )
  , ( 2, 'Tag2' )
  , ( 3, 'Tag3' )
  , ( 4, 'Tag4' )
  , ( 5, 'Tag5' )
  , ( 6, 'Tag6' )
;

CREATE TABLE TagValueTable ( FileId int, TagId int, theValue varchar(20) );

INSERT INTO TagValueTable (FileId, TagId, theValue)
VALUES 
    (1,1,'file1tag1value')
  , (1,2,'file1tag2value')
  , (1,4,'file1tag4value')
  , (2,1,'file2tag1value')
  , (2,4,'file2tag4value')
;  

查询:

SELECT ft.Name, ca.TagName, tvt.theValue 
FROM FileTable ft
CROSS APPLY (
  SELECT tt.ID AS TagID, tt.Name AS TagName
  FROM TagTable tt
) ca
LEFT OUTER JOIN TagValueTable tvt ON ft.ID = tvt.FileID
    AND ca.TagID = tvt.TagID
GO
Name       | TagName | theValue      
:--------- | :------ | :-------------
File1.docx | Tag1    | file1tag1value
File1.docx | Tag2    | file1tag2value
File1.docx | Tag3    | null          
File1.docx | Tag4    | file1tag4value
File1.docx | Tag5    | null          
File1.docx | Tag6    | null          
File2.xlsx | Tag1    | file2tag1value
File2.xlsx | Tag2    | null          
File2.xlsx | Tag3    | null          
File2.xlsx | Tag4    | file2tag4value
File2.xlsx | Tag5    | null          
File2.xlsx | Tag6    | null          
File3.pdf  | Tag1    | null          
File3.pdf  | Tag2    | null          
File3.pdf  | Tag3    | null          
File3.pdf  | Tag4    | null          
File3.pdf  | Tag5    | null          
File3.pdf  | Tag6    | null          

db <>提琴here