T-SQL选择Join 3 Tables

时间:2017-04-21 08:48:45

标签: sql sql-server tsql join

我目前正在使用SQL Server 2012上的T-SQL中的选择查询。这是一个复杂的查询,我想查询3个表中的列表。结果应如下所示:

期望输出:

ProjectId |    Title    | Manager   | Contact   | StatusId 
----------+-------------+-----------+-----------+-----------
1         |   projectX  |   1123    |  4453     |  1 
2         |   projectY  |   2245    |  5567     |  1
3         |   projectZ  |   3335    |  8899     |  1

我的3张桌子:

1)项目: ProjectId,ProjectDataId,MemberVersionId
2) ProjectData: ProjectDataId,Title,StatusId
3)成员: MemberId,MemberVersionId,MemberTypeId,EmployeeId

棘手的部分是实现版本控制。因此,随着时间的推移,项目成员可以更改,并且应该始终可以返回到以前的版本,这就是为什么我在 Project 和<之间使用 MemberVersionId 作为外键的原因EM>成员。表Project和ProjectData与ProjectDataId链接。

因此,1个项目有1个OfferData,1个项目有N个成员。

一些样本数据:
项目

ProjectId | ProjectDataId | MemberVersionId | 
----------+---------------+-----------------+
1         |   2           |   1             | 
2         |   3           |   1             |
3         |   4           |   1             |

ProjectData的

ProjectDataId |    Title    | StatusId 
--------------+-------------+-----------
2             |   projectX  |  1 
3             |   projectY  |  1
4             |   projectZ  |  1

成员: MemberTypeId 1 =经理,MemberTypeId 2 =联系人,3 =其他

MemberId | MemberVersionId | MemberTypeId | EmployeeId | 
---------+-----------------+--------------+------------+
1        |   1             |   1          |  1123      | 
2        |   1             |   2          |  4453      |
3        |   1             |   3          |  9999      |
4        |   2             |   1          |  2245      | 
5        |   2             |   2          |  5567      | 
6        |   2             |   3          |  9999      | 
7        |   3             |   1          |  3335      | 
8        |   3             |   2          |  8899      | 
9        |   3             |   3          |  9999      | 

我当前的查询如下所示:

SELECT ProjectId, Title, EmployeeId AS Manager, EmployeeId AS Contact, StatusId
FROM [MySchema].[Project] a,
     [MySchema].[ProjectData] b,
     [MySchema].[Members] c
WHERE a.ProjectDataId = b.ProjectDataId
  AND a.MemberVersionId = c.MemberVersionId

不幸的是,这还不行。你知道如何解决这个问题吗?

由于

5 个答案:

答案 0 :(得分:4)

这样的东西?

SELECT 
    p.ProjectId, 
    pd.Title, 
    mm.EmployeeId AS Manager, 
    mc.EmployeeId AS Contact, 
    pd.StatusId
FROM 
    [MySchema].[Project] p
    INNER JOIN [MySchema].[ProjectData] pd ON pd.ProjectDataId = p.ProjectDataId
    INNER JOIN [MySchema].[Members] mm ON mm.MemberVersionId = p.MemberVersionId AND mm.MemberTypeId = 1
    INNER JOIN [MySchema].[Members] mc ON mc.MemberVersionId = p.MemberVersionId AND mc.MemberTypeId = 2;

答案 1 :(得分:2)

你可以试试这个:

    SELECT ProjectId, Title, C.EmployeeId AS Manager, d.EmployeeId AS Contact, StatusId
FROM [MySchema].[Project] a
INNER JOIN    [MySchema].[ProjectData] b ON A.ProjectDataId=B.ProjectDataId
LEFT JOIN (SELECT * FROM [MySchema].[Members] WHERE MemberTypeID=1) c ON a.MemberVersionId=c.MemberVersionId  
LEFT JOIN  (SELECT * FROM [MySchema].[Members] WHERE MemberTypeID=2)  d ON a.MemberVersionId=d.MemberVersionId 

答案 2 :(得分:2)

您必须两次选择成员,一个用于经理,另一个用于联系:

SELECT ProjectId, Title, m.EmployeeId AS Manager, c.EmployeeId AS 
    Contact, StatusId
FROM [MySchema].[Project] a,
  [MySchema].[ProjectData] b,
  [MySchema].[Members] m
  [MySchema].[Members] c
WHERE a.ProjectDataId = b.ProjectDataId
  AND a.MemberVersionId = m.MemberVersionId and m.MemberTypeId = 1
  AND a.MemberVersionId = c.MemberVersionId and c.MemberTypeId = 2

答案 3 :(得分:2)

试试这个,

 SELECT ProjectId, Title, cmanager.EmployeeId AS Manager, ccon.EmployeeId AS 
 Contact, StatusId
 from  [MySchema].[ProjectData] b
 inner join [MySchema].[Project] a on b.ProjectDataId=a.ProjectDataId
 left join [MySchema].[Members] cmanager on cmanager.MemberVersionId = 
  a.MemberVersionId and cmanager.MemberTypeId=1
 left join [MySchema].[Members] ccon on ccon.MemberVersionId = 
 a.MemberVersionId and ccon.MemberTypeId=2  

答案 4 :(得分:2)

解决问题的最简单方法是在Project表中引入其他字段。您可以将其称为LatestMemberVersion(int,保持当前最高的MemberVersionId),这将是最新版本的关系,您可以添加更简单的IsLatestMemberVersion(位,保持1如果记录是最新的/活动的)。您可以使用ROW_NUMBER() OVER语句计算它们。

然后,查询将更改为:

SELECT ProjectId, Title, EmployeeId AS Manager, EmployeeId AS Contact, StatusId
FROM [MySchema].[Project] a,
     [MySchema].[ProjectData] b ON a.ProjectDataId = b.ProjectDataId
     [MySchema].[Members] c ON a.MemberVersionId = c.MemberVersionId
WHERE 
a.[IsLatestMemberVersion] = 1 -- alternative is a.[LatestMemberVersion] = a.[MemberVersionId]

此外,您还可以尝试两件事:

  1. 您可能想借用数据仓库的想法,即您希望将慢速变化维度类型1和2的组合

  2. 您可以尝试使用SQL Server功能,例如更改数据跟踪。但我没有这方面的经验,所以它可能无处可去。

  3. 最后一条建议,如果可以的话,永远不要在WHERE子句中写入连接条件。当您突然将JOIN更改为LEFT JOIN时,它不可读并且可能导致问题。 Microsoft本身建议在适用时使用ON而不是WHERE