我有一个关系表,其中有4个FK回到用户表...“标记”在某个实体上做某些事情的某些用户。
我在下面编造了一个制作例子。我不会解决下面的“人际关系”问题。但这是一个示例,用于显示我现有数据库中的内容。
问题是我从Person表中带回信息......但是基于关系表中的FK .....定义了(其他)人与我的关系。 (再次,这是一个组成的例子)
现在,我的现有查询“扁平化”数据,有很多LEFT连接。 Aka,我每人有4列数据,我现有的查询有20列(4列x 5人类型)....带别名列名。 “MotherLastName,MotherFirstName,MotherCreateDate”等等。
有没有办法在一个结果中将所有5行带回UNION ALL以外的所有内容。
可能没有,但我是C#开发人员,而不是TSQL超级大师。
如果最有效的话,我也可以带回5个结果(第一次尝试)。但我不认为是这种情况。
无论如何......只是一些星期五的思考 - 坦克。
感谢任何提示。
-- START TSQL
SET NOCOUNT ON
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[PersonSpecialPeople]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN
DROP TABLE [dbo].[PersonSpecialPeople]
END
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[Person]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN
DROP TABLE [dbo].[Person]
END
CREATE TABLE [dbo].[Person] (
[PersonUUID] [uniqueidentifier] NOT NULL,
[LastName] [varchar](64) NOT NULL,
[FirstName] [varchar](64) NOT NULL,
[CreateDate] [datetime] NOT NULL
)
GO
ALTER TABLE dbo.Person ADD CONSTRAINT PK_Person PRIMARY KEY NONCLUSTERED (PersonUUID)
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[PersonSpecialPeople]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN DROP TABLE [dbo].[PersonSpecialPeople]
END
GO
CREATE TABLE [dbo].[PersonSpecialPeople] (
[PersonSpecialPeopleSurrogateUUID] [uniqueidentifier] NOT NULL
, [CreateDate] [datetime] NOT NULL
, [MePersonUUID] [uniqueidentifier] NOT NULL
, [BestFriendPersonUUID] [uniqueidentifier] NOT NULL
, [SpousePersonUUID] [uniqueidentifier] NOT NULL
, [FatherPersonUUID] [uniqueidentifier] NOT NULL
, [MotherPersonUUID] [uniqueidentifier] NOT NULL
)
GO
ALTER TABLE dbo.PersonSpecialPeople ADD CONSTRAINT PK_PersonSpecialPeople PRIMARY KEY NONCLUSTERED (PersonSpecialPeopleSurrogateUUID)
GO
ALTER TABLE [dbo].[PersonSpecialPeople] ADD CONSTRAINT FK_ESP_MePersonUUID_To_PersonUUID FOREIGN KEY ([MePersonUUID]) REFERENCES dbo.Person (PersonUUID)
GO
ALTER TABLE [dbo].[PersonSpecialPeople] ADD CONSTRAINT FK_ESP_BestFriendPersonUUID_To_PersonUUID FOREIGN KEY (BestFriendPersonUUID) REFERENCES dbo.Person (PersonUUID)
GO
ALTER TABLE [dbo].[PersonSpecialPeople] ADD CONSTRAINT FK_ESP_SpousePersonUUID_To_PersonUUID FOREIGN KEY ([SpousePersonUUID]) REFERENCES dbo.Person (PersonUUID)
GO
ALTER TABLE [dbo].[PersonSpecialPeople] ADD CONSTRAINT FK_ESP_FatherPersonUUID_To_PersonUUID FOREIGN KEY ([FatherPersonUUID]) REFERENCES dbo.Person (PersonUUID)
GO
ALTER TABLE [dbo].[PersonSpecialPeople] ADD CONSTRAINT FK_ESP_MotherPersonUUID_To_PersonUUID FOREIGN KEY ([MotherPersonUUID]) REFERENCES dbo.Person (PersonUUID)
GO
declare @PersonUUID_Me [uniqueidentifier]
select @PersonUUID_Me = '11111111-1111-1111-1111-111111111111'
declare @PersonUUID_BestFriend [uniqueidentifier]
select @PersonUUID_BestFriend = '44444444-4444-4444-4444-444444444444'
declare @PersonUUID_Spouse [uniqueidentifier]
select @PersonUUID_Spouse = '55555555-5555-5555-5555-555555555555'
declare @PersonUUID_Father [uniqueidentifier]
select @PersonUUID_Father = '77777777-7777-7777-7777-777777777777'
declare @PersonUUID_Mother [uniqueidentifier]
select @PersonUUID_Mother = '88888888-8888-8888-8888-888888888888'
INSERT INTO [dbo].[Person] ( [PersonUUID] , [LastName] , [FirstName] , [CreateDate] )
Select @PersonUUID_Me , 'Coder', 'Granada' , CURRENT_TIMESTAMP
UNION ALL Select @PersonUUID_BestFriend , 'Stephenson', 'Leo' , CURRENT_TIMESTAMP
UNION ALL Select @PersonUUID_Spouse , 'Matheas', 'Mandie' , CURRENT_TIMESTAMP
UNION ALL Select @PersonUUID_Father , 'Coder', 'Daddy' , CURRENT_TIMESTAMP
UNION ALL Select @PersonUUID_Mother , 'Coder', 'Mommy' , CURRENT_TIMESTAMP
INSERT INTO [dbo].[PersonSpecialPeople] (
[PersonSpecialPeopleSurrogateUUID]
, [CreateDate]
, [MePersonUUID]
, [BestFriendPersonUUID]
, [SpousePersonUUID]
, [FatherPersonUUID]
, [MotherPersonUUID] )
Select NEWID() , CURRENT_TIMESTAMP , @PersonUUID_Me , @PersonUUID_BestFriend , @PersonUUID_Spouse , @PersonUUID_Father , @PersonUUID_Mother
/* Version One, Get 1 Result per Person "Type" */
Select [PersonUUID] , [LastName] , [FirstName] , [CreateDate] from [dbo].[Person] per
where per.PersonUUID = @PersonUUID_Me
Select [PersonUUID] , [LastName] , [FirstName] , per.[CreateDate] from [dbo].[Person] per
join [dbo].[PersonSpecialPeople] spec on per.PersonUUID = BestFriendPersonUUID
where spec.[MePersonUUID] = @PersonUUID_Me
Select [PersonUUID] , [LastName] , [FirstName] , per.[CreateDate] from [dbo].[Person] per
join [dbo].[PersonSpecialPeople] spec on per.PersonUUID = [SpousePersonUUID]
where spec.[MePersonUUID] = @PersonUUID_Me
Select [PersonUUID] , [LastName] , [FirstName] , per.[CreateDate] from [dbo].[Person] per
join [dbo].[PersonSpecialPeople] spec on per.PersonUUID = [FatherPersonUUID]
where spec.[MePersonUUID] = @PersonUUID_Me
Select [PersonUUID] , [LastName] , [FirstName] , per.[CreateDate] from [dbo].[Person] per
join [dbo].[PersonSpecialPeople] spec on per.PersonUUID = [MotherPersonUUID]
where spec.[MePersonUUID] = @PersonUUID_Me
/* Version Two, Get 1 Result , with Union-All, with a unique 'Tag' as first column */
Select [Relationship] = 'Me' , [PersonUUID] , [LastName] , [FirstName] , [CreateDate] from [dbo].[Person] per
where per.PersonUUID = @PersonUUID_Me
UNION ALL
Select [Relationship] = 'BestFriend' , [PersonUUID] , [LastName] , [FirstName] , per.[CreateDate] from [dbo].[Person] per
join [dbo].[PersonSpecialPeople] spec on per.PersonUUID = BestFriendPersonUUID
where spec.[MePersonUUID] = @PersonUUID_Me
UNION ALL
Select [Relationship] = 'Spouse' , [PersonUUID] , [LastName] , [FirstName] , per.[CreateDate] from [dbo].[Person] per
join [dbo].[PersonSpecialPeople] spec on per.PersonUUID = [SpousePersonUUID]
where spec.[MePersonUUID] = @PersonUUID_Me
UNION ALL
Select [Relationship] = 'Father' , [PersonUUID] , [LastName] , [FirstName] , per.[CreateDate] from [dbo].[Person] per
join [dbo].[PersonSpecialPeople] spec on per.PersonUUID = [FatherPersonUUID]
where spec.[MePersonUUID] = @PersonUUID_Me
UNION ALL
Select [Relationship] = 'Mother' , [PersonUUID] , [LastName] , [FirstName] , per.[CreateDate] from [dbo].[Person] per
join [dbo].[PersonSpecialPeople] spec on per.PersonUUID = [MotherPersonUUID]
where spec.[MePersonUUID] = @PersonUUID_Me
答案 0 :(得分:1)
如果您想避开UNION
,可以使用JOIN
和CASE
这样的结构:
首先创建一个关系表:
CREATE TABLE [rel] ([Relationship] varchar(20) NOT NULL PRIMARY KEY);
INSERT INTO [rel] VALUES('BestFriend'),('Spouse'),('Father'),('Mother');
然后您可以执行以下语句:
SELECT [rel].[Relationship], per.[PersonUUID], per.[LastName], per.[FirstName], per.[CreateDate]
FROM [dbo].[Person] per
CROSS JOIN [rel]
JOIN [dbo].[PersonSpecialPeople] spec ON
per.PersonUUID =
CASE [rel].[Relationship]
WHEN 'BestFriend' THEN BestFriendPersonUUID
WHEN 'Spouse' THEN SpousePersonUUID
WHEN 'Father' THEN FatherPersonUUID
WHEN 'Mother' THEN MotherPersonUUID
END
这使用了这样的事实,即连接不需要使用简单的a.colA = b.colB
条件,但您可以声明在条件中导致布尔值的任何内容。但是,大多数数据库优化器都更倾向于标准格式a.colA = b.colB
的连接。
答案 1 :(得分:1)
选项1: 使用UNPIVOT(http://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx)结帐。这是一个示例,它只使用一个UNION ALL来获取基本人员,然后是所有关系:
declare @PersonUUID_Me [uniqueidentifier]
select @PersonUUID_Me = '11111111-1111-1111-1111-111111111111';
SELECT Relationship = 'Me', p.PersonUUID, p.LastName, p.FirstName, p.CreateDate
FROM dbo.Person p
WHERE p.PersonUUID = @PersonUUID_Me
UNION ALL
SELECT Relationship = replace(unpvt.ReleationshipType, 'PersonUUID', ''), unpvt.RelPersonUUID, p.LastName, p.FirstName, unpvt.CreateDate
FROM
(
SELECT *
FROM dbo.PersonSpecialPeople
where MePersonUUID = @PersonUUID_Me
) sp
UNPIVOT (RelPersonUUID FOR ReleationshipType IN
([BestFriendPersonUUID]
, [SpousePersonUUID]
, [FatherPersonUUID]
, [MotherPersonUUID]
)
) as unpvt
INNER JOIN dbo.Person p ON p.PersonUUID = unpvt.RelPersonUUID
方案2: 您还可以重新考虑规范化数据库结构以具有以下新表:RelationshipType,PersonRelationship和摆脱[PersonSpecialPeople]。如果这是我理解的现有应用程序,那很难做到。
CREATE TABLE dbo.RelationshipType(RelationshipTypeID int not null primary key identity, Relationship nvarchar(50) not null)
go
CREATE TABLE dbo.PersonRelationship(
[PersonUUID] [uniqueidentifier] NOT NULL foreign key references dbo.Person(PersonUUID),
[RelPersonUUID] [uniqueidentifier] NOT NULL foreign key references dbo.Person(PersonUUID),
RelationshipTypeID int not null foreign key references dbo.RelationshipType(RelationshipTypeID),
CreateDate datetime not null
)
go
然后填充新表:
INSERT INTO dbo.RelationshipType(Relationship)
VALUES('BestFriend')
,('Spouse')
,('Father')
,('Mother')
;
INSERT INTO dbo.PersonRelationship(PersonUUID, RelPersonUUID, RelationshipTypeID, CreateDate)
VALUES(@PersonUUID_Me, @PersonUUID_BestFriend,1, current_timestamp)
,(@PersonUUID_Me, @PersonUUID_Spouse, 2, current_timestamp)
,(@PersonUUID_Me, @PersonUUID_Father,3, current_timestamp)
,(@PersonUUID_Me, @PersonUUID_Mother,4, current_timestamp)
最后添加了简化的select语句,不需要在新的RelationshipType中修改。注意:不要在实际生产代码中使用select *,单独列出每个列。
SELECT Relationship = cast('Me' as varchar(50)), p.*
FROM dbo.Person p
where p.PersonUUID = @PersonUUID_Me
union all
select rt.Relationship, p.*
from dbo.PersonRelationship r
inner join dbo.Person p on p.PersonUUID = r.RelPersonUUID
inner join dbo.RelationshipType rt on rt.RelationshipTypeID = r.RelationshipTypeID
where r.PersonUUID = @PersonUUID_Me