One Select代替UnionAll

时间:2012-04-12 07:46:42

标签: sql sql-server sql-server-2008 tsql view

这是我的表:

[Member]: 
{ [Id], [UserId], [UserName], [Email], [Status_Id], [MemberType_Id] }

[CustomerProfile] :
{ [Id], [Member_Id], [FirstName], [LastName], [SSN], [Gender], [PostalCode],[City_Id], [Address]}


[DealerProfile]:
{ [Id], [Member_Id], [FirstName], [LastName], [SSN], [Gender], [StoreName], [PostalCode], [City_Id], [Address] }


[ManagerProfile]
{ [Id], [Member_Id], [FirstName], [LastName], [SSN], [Gender] }

[City]:
{ [Id], [Title], [Province_Id] }

所以我需要创建所有成员和相关列的完整视图。

我必须提到[会员]。[Id]只是在3个个人资料表中的一个。这意味着一个会员可以拥有一种类型的客户,经销商或经理

首先,我将从以下选择查询开始:

 SELECT     
[ME].[Id] AS [MemberId],
[ME].[UserId],
[ME].[UserName],
[ME].[Status_Id],
[ST].[Title] AS [Status],
[ME].[MemberType_Id],
[MT].[Title] AS [MemberType],

CASE
    WHEN [MT].[Title]='Customer' THEN [CUP].[FirstName]
    WHEN [MT].[Title]='Dealer' THEN [DEP].[FirstName]
    WHEN [MT].[Title]='Manager' THEN [MAP].[FirstName]
    ELSE 'Unknown' END AS [FirstName],
CASE
    WHEN [MT].[Title]='Customer' THEN [CUP].[LastName]
    WHEN [MT].[Title]='Dealer' THEN [DEP].[LastName]
    WHEN [MT].[Title]='Manager' THEN [MAP].[LastName]
    ELSE 'Unknown' END AS [LastName]

FROM [Members].[Member] AS [ME]
INNER JOIN [Members].[MemberType] AS [MT] ON [ME].[MemberType_Id] = [MT].[Id]
INNER JOIN [Members].[Status] AS [ST] ON [ME].[Status_Id]=[ST].[Id]
INNER JOIN [Members].[ManagerProfile] AS [MAP] ON [ME].[Id]= [MAP].[Member_Id]
INNER JOIN [Members].[CustomerProfile] AS [CUP] ON [ME].[Id]=[CUP].[Member_Id]
INNER JOIN [Members].[DealerProfile] AS [DEP] ON [ME].[Id]=[DEP].[Member_Id];

但正如我之前在[会员]中所说的那样。[ID]只是在3个配置文件表中的一个,所以上面的查询返回null,我认为像这样使用Union All

(SELECT   
[ME].[Id] AS [MemberId],
[ME].[UserId],
[ME].[UserName],
[ME].[Status_Id],
[ST].[Title] AS [Status],
[ME].[MemberType_Id],
[MT].[Title] AS [MemberType],
[PR].[FirstName] AS [FirstName],
[PR].[LastName] AS [LastName]

FROM [Members].[Member] AS [ME]
INNER JOIN [Members].[MemberType] AS [MT] ON [ME].[MemberType_Id] = [MT].[Id]
INNER JOIN [Members].[Status] AS [ST] ON [ME].[Status_Id]=[ST].[Id]
INNER JOIN [Members].[CustomerProfile] AS [PR] ON [ME].[Id]=[PR].[Member_Id])
UNION ALL
(SELECT   
[ME].[Id] AS [MemberId],
[ME].[UserId],
[ME].[UserName],
[ME].[Status_Id],
[ST].[Title] AS [Status],
[ME].[MemberType_Id],
[MT].[Title] AS [MemberType],
[PR].[FirstName] AS [FirstName],
[PR].[LastName] AS [LastName]

FROM [Members].[Member] AS [ME]
INNER JOIN [Members].[MemberType] AS [MT] ON [ME].[MemberType_Id] = [MT].[Id]
INNER JOIN [Members].[Status] AS [ST] ON [ME].[Status_Id]=[ST].[Id]
INNER JOIN [Members].[DealerProfile] AS [PR] ON [ME].[Id]=[PR].[Member_Id])
UNION ALL
(SELECT   
[ME].[Id] AS [MemberId],
[ME].[UserId],
[ME].[UserName],
[ME].[Status_Id],
[ST].[Title] AS [Status],
[ME].[MemberType_Id],
[MT].[Title] AS [MemberType],
[PR].[FirstName] AS [FirstName],
[PR].[LastName] AS [LastName]

FROM [Members].[Member] AS [ME]
INNER JOIN [Members].[MemberType] AS [MT] ON [ME].[MemberType_Id] = [MT].[Id]
INNER JOIN [Members].[Status] AS [ST] ON [ME].[Status_Id]=[ST].[Id]
INNER JOIN [Members].[ManagerProfile] AS [PR] ON [ME].[Id]=[PR].[Member_Id])

那么你怎么看?这是创建视图的好方法,比如我的视图?是否有更好的方法来创建具有更好性能的视图而不是使用Union All?你对最短路和最佳表现的建议是什么?

2 个答案:

答案 0 :(得分:1)

UNION ALL经常会产生相当差的表现。

另一种方法是使用LEFT OUTER JOIN的内部查询,以及使用CASE语句选择相关字段的外部查询。我怀疑这会为你带来更好的表现。

为了简单起见,我们只使用您的客户资料和经销商资料表。当您将其扩展到连接中的其他表时,将应用相同的概念。另一种使用左外连接的方法看起来像这样:

create view MembersView as
select Id, 
case
    when not FirstName_cp is null then FirstName_cp
    when not FirstName_dp is null then First_name_dp
    else null
end as FirstName,
case
    when not LastName_cp is null then LastName_cp
    when not LastName_dp is null then Last_name_dp
    else null
end as LastName
from 
(

    select m.[Id] as Member_Id, cp.[FirstName] as FirstName_cp, 
           cp.[LastName] as LastName_cp, 
           dp.[FirstName] as FirstName_dp, 
           dp.[LastName] as LastName_dp
    from [Member] m
    left outer join [CustomerProfile] cp on
        m.Id = cp.Member_Id
    left outer join DealProfile dp on
        m.Id = dp.Member_Id
) as TBL

答案 1 :(得分:0)

带有LEFT JOIN

COALESCE

SELECT     
[ME].[Id] AS [MemberId],
[ME].[UserId],
[ME].[UserName],
[ME].[Status_Id],
[ST].[Title] AS [Status],
[ME].[MemberType_Id],
[MT].[Title] AS [MemberType],
[FirstName]=COALESCE([CUP].[FirstName],[DEP].[FirstName],[MAP].[FirstName],'Unknown'),
[LastName]=COALESCE([CUP].[LastName],[DEP].[LastName],[MAP].[LastName],'Unknown')
FROM [Members].[Member] AS [ME]
INNER JOIN [Members].[MemberType] AS [MT] ON [ME].[MemberType_Id] = [MT].[Id]
INNER JOIN [Members].[Status] AS [ST] ON [ME].[Status_Id]=[ST].[Id]
LEFT JOIN [Members].[ManagerProfile] AS [MAP] ON [ME].[Id]= [MAP].[Member_Id]
LEFT JOIN [Members].[CustomerProfile] AS [CUP] ON [ME].[Id]=[CUP].[Member_Id]
LEFT JOIN [Members].[DealerProfile] AS [DEP] ON [ME].[Id]=[DEP].[Member_Id];