我有三张桌子:
contacts
contact_phones
phone_types
表contacts
中的每个联系人在表contact_phones
中都有多个电话号码,每个电话号码都有一个type_id
来自表phone_types
(移动电话,办公室,家庭等) )
我需要一个查询,为每个联系人提供一行,为每种手机类型添加一列。
对于每个电话类型列,我需要一个逗号分隔的字符串,其中包含此联系人从表contact_phones
获得的所有电话号码。
例如:
first_name last_name Mobile_Phones Office_Phones
---------- --------- ---------------------- -------------
Amancio Ortega 0501111111,0502222222 031111111,032222222
Avi Zohar 0503333333 033333333
Beat Hirt 0504444444,0505555555 NULL
Ben Gurion 0501234567,05076545321 034444444,035555555
Dany Azriel 0506764879,05065587436 034847968
可以吗?
答案 0 :(得分:0)
您正在寻找 pivot 数据。有几种解决方案,复杂程度越来越高(就移动部件的数量而言):
PIVOT
次查询。为此,您必须事先知道所有列; PIVOT
与动态SQL结合使用,例如参见this question; 答案 1 :(得分:0)
这应该让你开始:
DECLARE @CONTACTS TABLE (ID INT IDENTITY(1,1), FNAME VARCHAR(100), LNAME VARCHAR(100))
DECLARE @CONTACTS_PHONE TABLE (ID INT IDENTITY(1,1), CONTACTID INT, TYPEID INT, PHONE VARCHAR(10))
DECLARE @PHONETYPE TABLE (ID INT IDENTITY(1,1), PHONETYPE VARCHAR(100))
INSERT INTO @CONTACTS (FNAME,LNAME)
SELECT 'JIGGS', 'JEDI'
INSERT INTO @PHONETYPE (PHONETYPE)
SELECT 'MOBILE' UNION
SELECT 'HOME' UNION
SELECT 'OFFICE'
INSERT INTO @CONTACTS_PHONE (CONTACTID, TYPEID, PHONE)
SELECT 1, 1, '5555555' UNION
SELECT 1, 1, '6666666' UNION
SELECT 1, 2, '0000000' UNION
SELECT 1, 2, '1111111' UNION
SELECT 1, 3, '4444444'
;WITH PIVOTSTUFF
AS
(
SELECT *
FROM (SELECT DISTINCT T.CONTACTID, PT.PHONETYPE,
PHONES = REPLACE(STUFF(
( SELECT ',' + PHONE AS [data()]
FROM @CONTACTS_PHONE AS X
WHERE X.CONTACTID = T.CONTACTID
AND X.TYPEID = T.TYPEID
ORDER BY PHONE
FOR XML PATH ('') ), 1, 1, ''), ' ,', ',')
FROM @CONTACTS_PHONE AS T
JOIN @PHONETYPE PT
ON T.TYPEID=PT.ID) DATATABLE
PIVOT(MIN([PHONES])
FOR PHONETYPE IN ([HOME],[MOBILE],[OFFICE])) PIVOTTABLE
)
SELECT C.ID, C.FNAME, C.LNAME, T.HOME, T.MOBILE, T.OFFICE
FROM PIVOTSTUFF T
JOIN @CONTACTS C
ON T.CONTACTID=C.ID
答案 2 :(得分:0)
编辑:您的原始帖子听起来好像您试图从逗号分隔列表中检索多个列,而不是相反。下面的代码旨在扭转这一过程。
=============================================== ==================================
我修改了一些类似问题的代码:让我知道这是否有帮助。正如评论中所指出的,这需要一个名为Numbers的表:我将它作为临时表并将其加载到我的下面的脚本中,但是最好将其永久化并加载一次。
-- Test Data
CREATE TABLE Contacts
(
Contacts_ID INT IDENTITY(1,1) NOT NULL,
First_Name VARCHAR(100) NOT NULL,
Last_Name VARCHAR(100) NOT NULL,
Mobile_Phones VARCHAR(100) NULL,
Office_Phones VARCHAR(100) NULL
)
INSERT INTO Contacts (First_Name, Last_Name, Mobile_Phones, Office_Phones)
SELECT 'Amancio', 'Ortega', '0501111111,0502222222', '031111111,032222222' UNION
SELECT 'Avi', 'Zohar', '0503333333', '033333333' UNION
SELECT 'Beat', 'Hirt', '0504444444,0505555555', NULL UNION
SELECT 'Ben', 'Gurion', '0501234567,05076545321', '034444444,035555555' UNION
SELECT 'Dany', 'Azriel', '0506764879,05065587436', '034847968'
-- Numbers table (for use in the formula): I would recommend creating a permanent table and populating it once. Make sure your count is higher than the length of your phone number columns.
CREATE TABLE #Numbers (Number INT NOT NULL)
INSERT INTO #Numbers (Number) SELECT 1
DECLARE @Limit INT
DECLARE @Counter INT
SET @Limit = 101
SET @Counter = (SELECT MAX(Number) FROM #Numbers)
WHILE @Counter < @Limit
BEGIN
INSERT INTO #Numbers (Number) SELECT MAX(Number) + 1 FROM #Numbers
SET @Counter = (SELECT MAX(Number) FROM #Numbers)
END
--SELECT * FROM #Numbers
-- Retrieve the information
SELECT
Contacts_ID,
First_Name,
Last_Name,
PhoneType,
CAST(LTRIM(RTRIM(NULLIF(SUBSTRING(',' + PhoneNumber + ',' , Number , CHARINDEX(',' , ',' + PhoneNumber + ',' , Number) - Number) , ''))) AS VARCHAR(10)) PhoneNumber
FROM #Numbers,
(SELECT
Contacts.Contacts_ID,
Contacts.First_Name,
Contacts.Last_Name,
Contacts.Mobile_Phones,
Contacts.Office_Phones
FROM Contacts
) P
UNPIVOT
(PhoneNumber FOR PhoneType IN
(
Mobile_Phones, Office_Phones
)) AS UP
WHERE
Number <= Len(',' + PhoneNumber + ',') AND SubString(',' + PhoneNumber + ',' , Number - 1, 1) = ',' AND
CharIndex(',' , ',' + PhoneNumber+ ',' , Number) - Number > 0
-- Clean up
/*
DROP TABLE Contacts
DROP TABLE #Numbers
*/