sql-server - 在列中显示 n 个电话号码

标签 sql-server tsql

你好 T-SQL 社区

我有一个项目需要在星期一结束前交付。我已经用尽了所有其他形式的研究,因此非常需要您的帮助!

我想做的是如下

返回一个将表1转换为表2的数据集

表 1:

Customer_No Name Telephone_No Address   Street_Name Postcode
=========== ==== ============ ========= =========== ========
635532      Mr X 0771111111   FLAT 1000 BEACH ROAD  BN23 5HT
635532      Mr X 0771112222   FLAT 1000 BEACH ROAD  BN23 5HT
635532      Mr X 01903773333  FLAT 1000 BEACH ROAD  BN23 5HT
635532      Mr X 01903774444  FLAT 1000 BEACH ROAD  BN23 5HT

为此...

表 2:

Customer_No Name Telephone_No_1 Telephone_No_2 Telephone_No_3 Telephone_No_4 Address   Street_Name Postcode
=========== ==== ============== ============== ============== ============== ========= =========== ======== 
635532      Mr X 0771111111     0771112222     01903773333    01903774444    FLAT 1000 BEACH ROAD  BN23 5HT

每个客户最多可以有 10 个电话号码。

为了清楚起见,以上内容在附图中显示

这是我目前构建的查询,但它受到我硬编码的电话字段数量的限制。我希望列是动态构建的

Select DISTINCT
       Customer_No,
       Name,
       ( SELECT MIN(REPLACE(Telephone_No, ' ', '') )
         FROM #PSR_Telephone t2
         WHERE t2.customer_No = t1.Customer_No
           AND LEFT(Telephone_No,2) = '07'
       ) AS [Telephone_No_1] , 
       ( SELECT MAX(REPLACE(Telephone_No, ' ', ''))
         FROM #PSR_Telephone t2
         WHERE t2.customer_No = t1.Customer_No
           AND LEFT(Telephone_No,2) = '07'
      ) AS [Telephone_No_2],
      ( SELECT MIN(REPLACE(Telephone_No, ' ', ''))
        FROM #PSR_Telephone t2
        WHERE t2.customer_No = t1.Customer_No
          AND LEFT(Telephone_No,2) <> '07'
      ) AS [Telephone_No_3],
      ( SELECT MAX(REPLACE(Telephone_No, ' ', ''))
        FROM #PSR_Telephone t2
        WHERE t2.customer_No= t1.Customer_No
          AND LEFT(Telephone_No,2) <> '07'
      ) AS [Telephone_No_4],
      Primary_Addressable_Object,
      Street_Name,
      Postcode
from #PSR_Telephone t1
where Customer_No = '635532'

非常感谢您对此提供的帮助。

非常感谢!

Example as picture

最佳答案

假设您使用的是 SQL-Server 2012 及更高版本

创建示例数据:

CREATE TABLE #temp (Customer_No INT, Name  VARCHAR(100),  Telephone_No VARCHAR(100),   Address VARCHAR(100), Street_Name VARCHAR(100), Postcode VARCHAR(100))

INSERT INTO #temp
VALUES
(635532,'Mr X','0771111111','FLAT 1000','BEACH ROAD','BN23 5HT'),          
(635532,'Mr X','0771112222','FLAT 1000','BEACH ROAD','BN23 5HT'),       
(635532,'Mr X','01903773333','FLAT 1000','BEACH ROAD','BN23 5HT'),     
(635532,'Mr X','01903774444' ,'FLAT 1000','BEACH ROAD','BN23 5HT')

使用带有 CASE 语句和窗口函数的 CTE 将电话号码放在正确标题下的查询:

;WITH CTE AS (
    SELECT  #temp.Customer_No, 
          #temp.Name,  
          CASE WHEN Row_number()OVER(partition BY Customer_No ORDER BY Telephone_No) = 1 THEN  #temp.Telephone_No END  AS Telephone_No_1, 
          CASE WHEN Row_number()OVER(partition BY Customer_No ORDER BY Telephone_No) = 2 THEN  #temp.Telephone_No END  AS Telephone_No_2, 
          CASE WHEN Row_number()OVER(partition BY Customer_No ORDER BY Telephone_No) = 3 THEN  #temp.Telephone_No END  AS Telephone_No_3, 
          CASE WHEN Row_number()OVER(partition BY Customer_No ORDER BY Telephone_No) = 4 THEN  #temp.Telephone_No END  AS Telephone_No_4, 
          #temp.Address, 
          #temp.Street_Name, 
          #temp.Postcode 
    FROM #temp)

 SELECT  CTE.Customer_No, 
       CTE.Name, 
       MAX(CTE.Telephone_No_1) Telephone_No_1, 
       MAX(CTE.Telephone_No_2) Telephone_No_2, 
       MAX(CTE.Telephone_No_3) Telephone_No_3, 
       MAX(CTE.Telephone_No_4) Telephone_No_4, 
       CTE.Address, 
       CTE.Street_Name, 
       CTE.Postcode
FROM CTE
GROUP BY      CTE.Customer_No, 
          CTE.Name, 
          CTE.Address,
          CTE.Street_Name,
          CTE.Postcode;

结果:

enter image description here

下面是上面的动态版本,因此您无需担心电话号码的数量:

创建示例数据

IF OBJECT_ID('tempdb..#TEMP') IS NOT NULL
    DROP TABLE #TEMP; 
CREATE TABLE #temp (Customer_No INT, Name  VARCHAR(100),  Telephone_No VARCHAR(100),   Address VARCHAR(100), Street_Name VARCHAR(100), Postcode VARCHAR(100))

INSERT INTO #temp
VALUES
(635532,'Mr X','0771111111','FLAT 1000','BEACH ROAD','BN23 5HT'),          
(635532,'Mr X','0771112222','FLAT 1000','BEACH ROAD','BN23 5HT'),       
(635532,'Mr X','01903773333','FLAT 1000','BEACH ROAD','BN23 5HT'),     
(635532,'Mr X','01903774444' ,'FLAT 1000','BEACH ROAD','BN23 5HT')

将生成类似于上述查询的查询的解决方案的动态部分:

IF OBJECT_ID('tempdb..#TEMP2') IS NOT NULL
    DROP TABLE #TEMP2; 

    SELECT  #temp.Customer_No, 
          #temp.Name,  
          Row_number()OVER(partition BY Customer_No ORDER BY Telephone_No) AS rn, 
          #temp.Telephone_No, 
          #temp.Address, 
          #temp.Street_Name, 
          #temp.Postcode INTO #temp2
    FROM #temp


DECLARE @SQL1 VARCHAR(max) ='';

SELECT @SQL1 = '
;WITH CTE AS (
    SELECT  #TEMP2.Customer_No, 
          #TEMP2.Name, ' 

SELECT  @SQL1+='CASE WHEN rn ='+CAST(rn AS VARCHAR)+'THEN  #TEMP2.Telephone_No END  AS Telephone_No_'+CAST(rn AS VARCHAR)+',' FROM #temp2

SELECT @SQL1+= '#TEMP2.Address, 
          #TEMP2.Street_Name, 
          #TEMP2.Postcode 
    FROM #TEMP2)

 SELECT  CTE.Customer_No, 
       CTE.Name,'

SELECT @SQL1+='MAX(CTE.Telephone_No_'+CAST(rn AS VARCHAR)+') AS Telephone_No_'+CAST(rn AS VARCHAR)+','FROM #temp2

SELECT @SQL1+='CTE.Address, 
       CTE.Street_Name, 
       CTE.Postcode
FROM CTE
GROUP BY      CTE.Customer_No, 
          CTE.Name, 
          CTE.Address,
          CTE.Street_Name,
          CTE.Postcode;'



 PRINT(@SQL1)

 EXECUTE (@SQL1)

打印语句的结果:

enter image description here

整个查询的结果:

enter image description here

关于sql-server - 在列中显示 n 个电话号码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35369331/

相关文章:

sql-server - 如何在 SQL Server Always Encrypted 列上使用 Like 运算符?

sql-server - 附加数据库

c# - 使用 SqlBulkCopy 插入数据时出错

sql - t sql select语句中的子查询

SQL Server Full Text Search Condition for FORMSOF for phrase 排除停用词

sql-server - 为什么当 INT 在 SQL 条件中用于列类型的 INT 是 varchar 时 SQL 语句失败,并且当数字类型 colum 添加为条件时运行没有任何错误

c# - 在数据库中存储数组的最佳方式

c# - 从 .NET CLR UDF 调用 T-SQL 内置函数的有效方法?

mysql - 按 t1.date 连接不相关的表(t2.startdate 和 t2.enddate 之间)

sql - 透视和交叉应用