我有多个表需要加入并展平。用户表,用户的属性类型表以及包含属性值的表。以下是users表的示例:
Id User
1 Sam
2 Bill
和属性类型:
Id Order Property
1 30 Weight
2 20 Hair Color
3 10 Eye Color
和财产价值:
UserId PropertyId Value
1 3 Blue
1 2 Blond
1 1 170
2 3 Brown
2 2 Black
2 1 180
我希望得到这样的结果:
User Eye Color Hair Color Weight
Sam Blue Blond 170
Bill Brown Black 180
请注意,属性列的顺序由属性类型中的Order列驱动。而且我不会提前知道属性名称是什么或者可能有多少。
这是创建3个表的代码。
DECLARE @TableA TABLE (ProperyId int, DisplayOrder int, Property varchar(50))
DECLARE @TableB TABLE (UserId int, [User] varchar(50))
DECLARE @TableC TABLE (UserId int, PropertyId varchar(50), Value varchar(50))
INSERT INTO @TableA SELECT 1, 30, 'Weight'
INSERT INTO @TableA SELECT 2, 20, 'Hair Color'
INSERT INTO @TableA SELECT 3, 30, 'Eye Color'
INSERT INTO @TableB SELECT 1, 'Sam'
INSERT INTO @TableB SELECT 2, 'Bill'
INSERT INTO @TableC SELECT 1, 3, 'Blue'
INSERT INTO @TableC SELECT 1, 2, 'Blond'
INSERT INTO @TableC SELECT 1, 1, '170'
INSERT INTO @TableC SELECT 2, 3, 'Brown'
INSERT INTO @TableC SELECT 2, 2, 'Black'
INSERT INTO @TableC SELECT 2, 1, '180'
select * from @TableA
select * from @TableB
select * from @TableC
提前致谢!史蒂夫。
试图在将表构建为临时表时使其工作太麻烦了,所以我更改了模式代码以使它们成为实际表(并在其中一个列名中更正了拼写错误)。更改的模式代码和结果代码可以在SQL Fiddle上找到here,这样你就可以测试它,但我也把结果代码放在下面。关键是你必须使用SQL来编写你需要的SQL(因为你不知道所有列将是什么):
DECLARE
@Columns NVARCHAR(MAX),
@SQL_Statement NVARCHAR(MAX)
SELECT @Columns = ISNULL( @Columns + ', ', '') + '[' + s.Property + ']' FROM (SELECT DISTINCT [Property] FROM TableA) AS s
SELECT @SQL_Statement = '
WITH cte_Flat AS
(
SELECT
b.[User],
a.[Property],
C.[Value]
FROM
TableC AS c
JOIN
TableB AS b
ON
c.[UserID] = b.[UserID]
JOIN
TableA AS a
ON
c.[PropertyId] = a.[PropertyID]
)
SELECT
[User],
' + @Columns + '
FROM
cte_Flat
PIVOT
(
MAX([Value])
for [Property] in (' + @Columns + ')
) AS u'
EXEC SP_EXECUTESQL @SQL_Statement = @SQL_Statement
我有一个解决方案给你。您可以在查询中使用第二个表(TableA)在属性,属性和订单中进行编码。所以,你实际上并不需要它。您可以使用第一个和第三个表格获得相同的结果!这是因为用户不会有两种类型的头发,眼睛和重量,因此userID和PropertyId的组合将成为第三个表(TableC)中的关键。
在这种情况下,我喜欢做的是为每个Property创建一个子查询,然后将它们与user表连接起来。我知道这可以是更多的代码,但在我处理更复杂的数据时总是更容易。
WITH EyeColor AS
(
SELECT
UserId
, Value
FROM
TableC
WHERE
PropertyId = 3
)
, HairColor AS
(
SELECT
UserId
, Value
FROM
TableC
WHERE
PropertyId = 2
)
, Weight AS
(
SELECT
UserId
, Value
FROM
TableC
WHERE
PropertyId = 2
)
------------------------------------
SELECT
u.User AS NAME
, e.Value AS EYECOLOR
, h.Value AS HAIRCOLOR
, w.Value AS WEIGHT
FROM
TableB u
LEFT JOIN
EyeColor e
ON u.Id = e.UserId
LEFT JOIN
HairColor h
ON u.Id = h.UserId
LEFT JOIN
Weight w
ON u.Id = w.UserId
祝好运!