我在SQL Server中有一个混乱的表(对不起,这是我从供应商那里得到它的方式)。我已经大大减少了它,所以我可以专注于这个问题,虽然我显然已经看不到森林的树木了。
目标:对这些数据进行UNPIVOT,但我似乎无法正确理解逻辑。
问题:怪癖是我需要列标题的子字符串作为数据的一部分 - 如下面的示例所示。
Rextester示例数据ggeffects-package
我的表,一旦导入就像这样:
+----+----------+--------------------+--------------------+-------------------+-------------------+
| id | person | contact 1 - phone | contact 2 - phone | contact 1 - email | contact 2 - email |
+----+----------+--------------------+--------------------+-------------------+-------------------+
| 1 | john doe | 123456 | 234567 | john@doe.me | johndoe@gmail.com |
| 2 | jane doe | 654321 | 765432 | Jane@doe.me | NULL |
+----+----------+--------------------+--------------------+-------------------+-------------------+
预期输出:
+----+----------+---------------+--------+-------------------+
| id | person | contactNumber | phone | email |
+----+----------+---------------+--------+-------------------+
| 1 | John Doe | 1 | 123456 | john@doe.me |
| 1 | John Doe | 2 | 234567 | johndoe@gmail.com |
| 2 | Jane Doe | 1 | 654321 | jane@doe.me |
| 2 | Jane Doe | 2 | 765432 | janedoe@gmail.com |
+----+----------+---------------+--------+-------------------+
答案 0 :(得分:2)
万一你需要去"动态"从某种意义上说,你不知道列(或联系人)可能如何
示例强>
Declare @YourTable Table ([id] varchar(50),[person] varchar(50),[contact 1 - phone] varchar(50),[contact 2 - phone] varchar(50),[contact 1 - email] varchar(50),[contact 2 - email] varchar(50))
Insert Into @YourTable Values
(1,'john doe',123456,234567,'john@doe.me','johndoe@gmail.com')
,(2,'jane doe',654321,765432,'Jane@doe.me',NULL)
Select id
,person
,contactNumber
,phone = max(case when Item like '%phone%' then value end)
,email = max(case when Item like '%email%' then value end)
From (
Select A.ID
,A.Person
,contactNumber = cast(substring(Item,patindex('%[0-9]%',item),2) as int)
,C.*
From @YourTable A
Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
Cross Apply (
Select Item = replace(a.value('local-name(.)','varchar(100)'),'_x0020_',' ')
,Value = a.value('.','varchar(max)')
From B.XMLData.nodes('/row') as C1(n)
Cross Apply C1.n.nodes('./@*') as C2(a)
Where a.value('local-name(.)','varchar(100)') not in ('id','person')
) C
) A
Group By id,person,contactNumber
<强>返回强>
编辑 - 简化
Select A.ID
,A.Person
,C.*
From @YourTable A
Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
Cross Apply (
Select Item = replace(a.value('local-name(.)','varchar(100)'),'_x0020_',' ')
,Value = a.value('.','varchar(max)')
From B.XMLData.nodes('/row') as C1(n)
Cross Apply C1.n.nodes('./@*') as C2(a)
Where a.value('local-name(.)','varchar(100)') not in ('id','person')
) C
返回
答案 1 :(得分:1)
如果联系人2或者电子邮件或电话不为空,您可以使用UNION
生成联系人1的所有记录和联系人2的所有记录。如果contact-2的电子邮件为空,请使用COALESCE
来使用contact-1的电子邮件。
SELECT id, person, 1 [contactNumber], [contact 1 - phone] [phone], [contact 1 - email] [email]
FROM #TEST
UNION
SELECT id, person, 2
, [contact 2 - phone]
, COALESCE([contact 2 - email], [contact 1 - email])
FROM #TEST
WHERE [contact 2 - phone] IS NOT NULL OR [contact 2 - email] IS NOT NULL
答案 2 :(得分:1)
你试过这个吗?
SELECT
id,
person,
1 as contactnumber,
[contact 1 - phone] as phone,
[contact 1 - email] as email
FROM Table
UNION
SELECT
id,
person,
2 as contactnumber,
[contact 2 - phone] as phone,
[contact 2 - email] as email
FROM Table