欧美日韩精品在线,国内精品久久久久久久久,一级毛片恃级毛片直播,清纯唯美亚洲综合欧美色

一列保存多個(gè)ID(將多個(gè)用逗號(hào)隔開的ID轉(zhuǎn)換成用逗號(hào)隔開的名稱)_Mssql數(shù)據(jù)庫(kù)教程

編輯Tag賺U幣
教程Tag:暫無(wú)Tag,歡迎添加,賺取U幣!

推薦:經(jīng)典SQL語(yǔ)句大全
一、基礎(chǔ) 1、說(shuō)明:創(chuàng)建數(shù)據(jù)庫(kù) CREATE DATABASE database - name 2、說(shuō)明:刪除數(shù)據(jù)庫(kù) drop database dbname 3、說(shuō)明:備份sql server -- - 創(chuàng)建 備份數(shù)據(jù)的 device USE master EXEC sp_addumpdevice ' disk ' , ' testBack ' , ' c:\mssql7backup\MyNwind_1.dat ' --

背景:在做項(xiàng)目時(shí),經(jīng)常會(huì)遇到這樣的表結(jié)構(gòu)在主表的中有一列保存的是用逗號(hào)隔開ID。如,當(dāng)一個(gè)員工從屬多個(gè)部門時(shí)、當(dāng)一個(gè)項(xiàng)目從屬多個(gè)城市時(shí)、當(dāng)一個(gè)設(shè)備從屬多個(gè)項(xiàng)目時(shí),很多人都會(huì)在員工表中加入一個(gè)deptIds VARCHAR(1000)列(本文以員工從屬多個(gè)部門為例),用以保存部門編號(hào)列表(很明顯這不符合第一范式,但很多人這樣設(shè)計(jì)了,在這篇文章中我們暫不討論在這種應(yīng)用場(chǎng)景下,如此設(shè)計(jì)的對(duì)與錯(cuò),有興趣的可以在回復(fù)中聊聊),然后我們?cè)诓樵兞斜碇行枰吹竭@個(gè)員工從屬哪些部門。

初始化數(shù)據(jù):

部門表、員工表數(shù)據(jù):

  1. IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Department]')) 
  2. DROP TABLE [dbo].Department 
  3. GO 
  4. --部門表 
  5. CREATE TABLE Department 
  6.     id int
  7.     name nvarchar(50) 
  8. INSERT INTO Department(id,name
  9. SELECT 1,'人事部' 
  10. UNION  
  11. SELECT 2,'工程部' 
  12. UNION  
  13. SELECT 3,'管理部' 
  14.  
  15. SELECT * FROM Department 
  16.  
  17.  
  18. IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Employee]')) 
  19. DROP TABLE [dbo].Employee 
  20. GO 
  21. --員工表 
  22. CREATE TABLE Employee 
  23.     id int,  
  24.     name nvarchar(20), 
  25.     deptIds varchar(1000) 
  26. INSERT INTO Employee(id,name,deptIds) 
  27. SELECT 1,'蔣大華','1,2,3' 
  28. UNION 
  29. SELECT 2,'小明','1' 
  30. UNION  
  31. SELECT 3,'小華','' 
  32.  
  33. SELECT * FROM Employee 

希望得到的結(jié)果:

解決方法:

第一步,是得到如下的數(shù)據(jù)。即將員工表集合與相關(guān)的部門集合做交叉連接,其中使用了fun_SplitIds函數(shù)(作用是將ids分割成id列表),然后員工集合與這個(gè)得到的集合做交叉連接

SELECT E.*,ISNULL(D.name,'') AS deptName FROM Employee AS E     OUTER APPLY dbo.fun_SplitIds(E.deptIds) AS DID    LEFT JOIN Department AS D ON DID.ID=D.id;

 

第二步,已經(jīng)得到了如上的數(shù)據(jù),然后要做的就是根據(jù)ID分組,并對(duì)deptName列做聚合操作,但可惜的是SQL SERVER還沒有提供對(duì)字符串做聚合的操作。但想到,我們處理樹形結(jié)構(gòu)數(shù)據(jù)時(shí),用CTE來(lái)做關(guān)系數(shù)據(jù),做成有樹形格式的數(shù)據(jù),如此我們也可以將這個(gè)問(wèn)題轉(zhuǎn)換成做樹形格式的問(wèn)題,代碼如下:

  1. WITH EmployeT AS
  2. --員工的基本信息(使用OUTER APPLY將多個(gè)ID拆分開來(lái),然后與部門表相關(guān)聯(lián)) 
  3. --此時(shí)已將員工表所存的IDS分別與部門相關(guān)聯(lián),下面需要將此集合中的deptName聚合成一個(gè)記錄 
  4. SELECT E.*,ISNULL(D.name,''AS deptName 
  5. FROM Employee AS E  
  6.    OUTER APPLY dbo.fun_SplitIds(E.deptIds) AS DID 
  7.    LEFT JOIN Department AS D ON DID.ID=D.id 
  8. ),mike AS
  9.    SELECT id,name,deptIds,deptName 
  10.       ,ROW_NUMBER()OVER(PARTITION BY id ORDER BY id) AS level_num 
  11.    FROM EmployeT 
  12. ),mike2 AS
  13.    SELECT id,name,deptIds,CAST(deptName AS NVARCHAR(100)) AS deptName,level_num  
  14.    FROM mike 
  15.    WHERE level_num=1 
  16.    UNION ALL 
  17.    SELECT m.id,m.name,m.deptIds,CAST(m2.deptName+','+m.deptName AS NVARCHAR(100)) AS deptName,m.level_num  
  18.    FROM mike AS m 
  19.       INNER JOIN mike2 AS m2 ON m.ID=m2.id AND m.level_num=m2.level_num+1 
  20. ),maxMikeByIDT AS
  21.        SELECT id,MAX(level_num) AS level_num 
  22.        FROM mike2  
  23.        GROUP BY ID 
  24.  
  25. SELECT A.id,A.name,A.deptIds,A.deptName 
  26. FROM mike2 AS A  
  27.    INNER JOIN maxMikeByIDT AS B ON A.id=B.ID AND A.level_num=B.level_num 
  28. ORDER BY A.id OPTION (MAXRECURSION 0) 
結(jié)果如下:

全部SQL:

  1. IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Department]')) 
  2. DROP TABLE [dbo].Department 
  3. GO 
  4. --部門表 
  5. CREATE TABLE Department 
  6.     id int
  7.     name nvarchar(50) 
  8. INSERT INTO Department(id,name
  9. SELECT 1,'人事部' 
  10. UNION  
  11. SELECT 2,'工程部' 
  12. UNION  
  13. SELECT 3,'管理部' 
  14.  
  15. SELECT * FROM Department 
  16.  
  17.  
  18. IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Employee]')) 
  19. DROP TABLE [dbo].Employee 
  20. GO 
  21. --員工表 
  22. CREATE TABLE Employee 
  23.     id int,  
  24.     name nvarchar(20), 
  25.     deptIds varchar(1000) 
  26. INSERT INTO Employee(id,name,deptIds) 
  27. SELECT 1,'蔣大華','1,2,3' 
  28. UNION 
  29. SELECT 2,'小明','1' 
  30. UNION  
  31. SELECT 3,'小華','' 
  32.  
  33. SELECT * FROM Employee 
  34.  
  35. --創(chuàng)建一個(gè)表值函數(shù),用來(lái)拆分用逗號(hào)分割的數(shù)字串,返回只有一列數(shù)字的表 
  36. IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[fun_SplitIds]')) 
  37. DROP FUNCTION [dbo].fun_SplitIds 
  38. GO 
  39. CREATE FUNCTION dbo.fun_SplitIds( 
  40.     @Ids nvarchar(1000) 
  41. RETURNS @t_id TABLE (id VARCHAR(36)) 
  42. AS 
  43. BEGIN 
  44.     DECLARE @i INT,@j INT,@l INT,@v VARCHAR(36); 
  45.     SET @i = 0; 
  46.     SET @j = 0; 
  47.     SET @l = len(@Ids); 
  48.     while(@j < @l) 
  49.     begin 
  50.        SET @j = charindex(',',@Ids,@i+1); 
  51.        IF(@j = 0) set @j = @l+1; 
  52.        SET @v = cast(SUBSTRING(@Ids,@i+1,@j-@i-1) as VARCHAR(36)); 
  53.        INSERT INTO @t_id VALUES(@v) 
  54.        SET @i = @j; 
  55.     END 
  56.     RETURN
  57. END 
  58. GO 
  59.  
  60.  
  61. ;WITH EmployeT AS
  62. --員工的基本信息(使用OUTER APPLY將多個(gè)ID拆分開來(lái),然后與部門表相關(guān)聯(lián)) 
  63. --此時(shí)已將員工表所存的IDS分別與部門相關(guān)聯(lián),下面需要將此集合中的deptName聚合成一個(gè)記錄 
  64. SELECT E.*,ISNULL(D.name,''AS deptName 
  65. FROM Employee AS E  
  66.    OUTER APPLY dbo.fun_SplitIds(E.deptIds) AS DID 
  67.    LEFT JOIN Department AS D ON DID.ID=D.id 
  68. ),mike AS
  69.    SELECT id,name,deptIds,deptName 
  70.       ,ROW_NUMBER()OVER(PARTITION BY id ORDER BY id) AS level_num 
  71.    FROM EmployeT 
  72. ),mike2 AS
  73.    SELECT id,name,deptIds,CAST(deptName AS NVARCHAR(100)) AS deptName,level_num  
  74.    FROM mike 
  75.    WHERE level_num=1 
  76.    UNION ALL 
  77.    SELECT m.id,m.name,m.deptIds,CAST(m2.deptName+','+m.deptName AS NVARCHAR(100)) AS deptName,m.level_num  
  78.    FROM mike AS m 
  79.       INNER JOIN mike2 AS m2 ON m.ID=m2.id AND m.level_num=m2.level_num+1 
  80. ),maxMikeByIDT AS
  81.        SELECT id,MAX(level_num) AS level_num 
  82.        FROM mike2  
  83.        GROUP BY ID 
  84.  
  85.  
  86. SELECT A.id,A.name,A.deptIds,A.deptName 
  87. FROM mike2 AS A  
  88.    INNER JOIN maxMikeByIDT AS B ON A.id=B.ID AND A.level_num=B.level_num 
  89. ORDER BY A.id OPTION (MAXRECURSION 0) 

分享:SQL Server字符串切割
結(jié)果: 645002*01 --1 45854 --2 183677

來(lái)源:未知//所屬分類:Mssql數(shù)據(jù)庫(kù)教程/更新時(shí)間:2012-07-20
相關(guān)Mssql數(shù)據(jù)庫(kù)教程