SQL合并列值两种新方法

      在SQL SERVER中,有时需要合多列值到行的需求,常见的方法有:1.创建自定义函数,2.使用游标法进行字符串合并。3.使用临

时表实现字符串合并。
     数据:

        DEPTNO EMPS
------ ----------
10 CLARK
10 KING
10 MILLER
20 SMITH
20 ADAMS
20 FORD
20 SCOTT
20 JONES
30 ALLEN
30 BLAKE
30 MARTIN
30 JAMES
30 TURNER
30 WARD


期望结果:

	 DEPTNO EMPS
------- ------------------------------------
10 CLARK,KING,MILLER
20 SMITH,JONES,SCOTT,ADAMS,FORD
30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES


   方法:
-1.xmloutput---------------------------------------
--
http://wintersun.cnblogs.com
--
-------------------------------------------------
SELECT *
FROM(
    
SELECT DISTINCT 
        deptno
    
FROM emp
)A
OUTER APPLY(
    
SELECT 
        
[values]= STUFF(REPLACE(REPLACE(
            (
                
SELECT ENAME FROM emp N
                
WHERE deptno = A.deptno
                
FOR XML AUTO
            ), 
'<N ENAME="'','), '"/>'''), 11'')
)N

-2.---using CTE----------------------------------------
--
Creating a Delimited List from Table Rows
--
http://wintersun.cnblogs.com
--
-----------------------------------------------------
  with x (deptno, cnt, list, empno, len)
         
as (
     
select deptno, count(*over (partition by deptno),
            
cast(ename as varchar(100)),
            empno,
            
1
       
from emp
      
union all
     
select x.deptno, x.cnt,
            
cast(x.list + ',' + e.ename as varchar(100)),
            e.empno, x.
len+1
       
from emp e, x
     
where e.deptno = x.deptno
       
and e.empno > x. empno
                )
     
select deptno,list
       
from x
      
where len = cnt
      
order by 1


测试的用的表与数据:
ContractedBlock.gifExpandedBlockStart.giftableAndData
    
/*
 * SC Header, do not delete!
 *
 * $Revision:  $
 * $Date: 2008-11-30 $
 * $Author: Administrator $
 * $Archive: $
 *
 * Purpose:
 *   To recreate the Data in emp Table
 * Change History:
 *
 
*/

USE NORTHWND
GO
BEGIN TRANSACTION
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
-- Backup the table
--
#region
DECLARE 
    
@TimeStamp VARCHAR(30),
    
@SQL       NVARCHAR(4000),
    
@Revision  NVARCHAR(20),
    
@StatusMessage VARCHAR(400)
    
SET @Revision = CAST(REPLACE(REPLACE('$Revision: $''Revision:'''), '$'''AS INT)    
SET @TimeStamp = REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(25),GETDATE(),120),' ',''),'-',''),':','')   
SET @SQL = 'SELECT * INTO [dbo].[emp_' + @Revision + '_' + @TimeStamp + '] FROM [dbo].[emp]'
    
    
EXEC sp_executesql @SQL

IF (@@ROWCOUNT = 0 AND (SELECT COUNT(*FROM [dbo].[emp]> 0)
OR (@@ERROR > 0)
BEGIN
    
RAISERROR('not enough rows inserted into the backup table'161)
    
GOTO ErrorHandler
END
ELSE
BEGIN
    
SET @StatusMessage = 'All existing data was copied into the table [dbo].[emp_' + @Revision + '_' + @TimeStamp + ']'
    
PRINT @StatusMessage
END
--#endregion

DELETE FROM [dbo].[emp]
IF @@ERROR > 0
BEGIN
    
PRINT 'Delete Failed, roll back the transaction'
    
GOTO ErrorHandler
END
    
-- Setup the XML document that is the table data, this text string can be up to 2gb in size.
--
#region
DECLARE @DocumentHandle INT
EXEC dbo.sp_xml_preparedocument @DocumentHandle OUTPUT, N'
<?xml version="1.0" encoding="utf-16"?>
<empRows>
    <empRow>
        <EMPNO>7369</EMPNO>
        <ENAME>SMITH</ENAME>
        <JOB>CLERK</JOB>
        <MGR>7902</MGR>
        <HIREDATE>17-DEC-1980</HIREDATE>
        <SAL>800</SAL>
        <COMM />
        <DEPTNO>20</DEPTNO>
    </empRow>
    <empRow>
        <EMPNO>7499</EMPNO>
        <ENAME>ALLEN</ENAME>
        <JOB>SALESMAN</JOB>
        <MGR>7698</MGR>
        <HIREDATE>20-FEB-1981</HIREDATE>
        <SAL>1600</SAL>
        <COMM>300</COMM>
        <DEPTNO>30</DEPTNO>
    </empRow>
    <empRow>
        <EMPNO>7521</EMPNO>
        <ENAME>WARD</ENAME>
        <JOB>SALESMAN</JOB>
        <MGR>7698</MGR>
        <HIREDATE>22-FEB-1981</HIREDATE>
        <SAL>1250</SAL>
        <COMM>500</COMM>
        <DEPTNO>30</DEPTNO>
    </empRow>
    <empRow>
        <EMPNO>7566</EMPNO>
        <ENAME>JONES</ENAME>
        <JOB>MANAGER</JOB>
        <MGR>7839</MGR>
        <HIREDATE>02-APR-1981</HIREDATE>
        <SAL>2975</SAL>
        <COMM />
        <DEPTNO>20</DEPTNO>
    </empRow>
    <empRow>
        <EMPNO>7654</EMPNO>
        <ENAME>MARTIN</ENAME>
        <JOB>SALESMAN</JOB>
        <MGR>7698</MGR>
        <HIREDATE>28-SEP-1981</HIREDATE>
        <SAL>1250</SAL>
        <COMM>1400</COMM>
        <DEPTNO>30</DEPTNO>
    </empRow>
    <empRow>
        <EMPNO>7698</EMPNO>
        <ENAME>BLAKE</ENAME>
        <JOB>MANAGER</JOB>
        <MGR>7839</MGR>
        <HIREDATE>01-MAY-1981</HIREDATE>
        <SAL>2850</SAL>
        <COMM />
        <DEPTNO>30</DEPTNO>
    </empRow>
    <empRow>
        <EMPNO>7782</EMPNO>
        <ENAME>CLARK</ENAME>
        <JOB>MANAGER</JOB>
        <MGR>7839</MGR>
        <HIREDATE>09-JUN-1981</HIREDATE>
        <SAL>2450</SAL>
        <COMM />
        <DEPTNO>10</DEPTNO>
    </empRow>
    <empRow>
        <EMPNO>7788</EMPNO>
        <ENAME>SCOTT</ENAME>
        <JOB>ANALYST</JOB>
        <MGR>7566</MGR>
        <HIREDATE>09-DEC-1982</HIREDATE>
        <SAL>3000</SAL>
        <COMM />
        <DEPTNO>20</DEPTNO>
    </empRow>
    <empRow>
        <EMPNO>7839</EMPNO>
        <ENAME>KING</ENAME>
        <JOB>PRESIDENT</JOB>
        <MGR />
        <HIREDATE>17-NOV-1981</HIREDATE>
        <SAL>5000</SAL>
        <COMM />
        <DEPTNO>10</DEPTNO>
    </empRow>
    <empRow>
        <EMPNO>7844</EMPNO>
        <ENAME>TURNER</ENAME>
        <JOB>SALESMAN</JOB>
        <MGR>7698</MGR>
        <HIREDATE>08-SEP-1981</HIREDATE>
        <SAL>1500</SAL>
        <COMM>0</COMM>
        <DEPTNO>30</DEPTNO>
    </empRow>
    <empRow>
        <EMPNO>7876</EMPNO>
        <ENAME>ADAMS</ENAME>
        <JOB>CLERK</JOB>
        <MGR>7788</MGR>
        <HIREDATE>12-JAN-1983</HIREDATE>
        <SAL>1100</SAL>
        <COMM />
        <DEPTNO>20</DEPTNO>
    </empRow>
    <empRow>
        <EMPNO>7900</EMPNO>
        <ENAME>JAMES</ENAME>
        <JOB>CLERK</JOB>
        <MGR>7698</MGR>
        <HIREDATE>03-DEC-1981</HIREDATE>
        <SAL>950</SAL>
        <COMM />
        <DEPTNO>30</DEPTNO>
    </empRow>
    <empRow>
        <EMPNO>7902</EMPNO>
        <ENAME>FORD</ENAME>
        <JOB>ANALYST</JOB>
        <MGR>7566</MGR>
        <HIREDATE>03-DEC-1981</HIREDATE>
        <SAL>3000</SAL>
        <COMM />
        <DEPTNO>20</DEPTNO>
    </empRow>
    <empRow>
        <EMPNO>7934</EMPNO>
        <ENAME>MILLER</ENAME>
        <JOB>CLERK</JOB>
        <MGR>7782</MGR>
        <HIREDATE>23-JAN-1982</HIREDATE>
        <SAL>1300</SAL>
        <COMM />
        <DEPTNO>10</DEPTNO>
    </empRow>
</empRows>
'
--#endregion
INSERT INTO [dbo].[emp] (
    
[EMPNO],
    
[ENAME],
    
[JOB],
    
[MGR],
    
[HIREDATE],
    
[SAL],
    
[COMM],
    
[DEPTNO]
)
SELECT 
    
[EMPNO],
    
[ENAME],
    
[JOB],
    
[MGR],
    
[HIREDATE],
    
[SAL],
    
[COMM],
    
[DEPTNO]
FROM OPENXML(@DocumentHandle'empRows/empRow'2WITH ( 
    
[EMPNO] INT,
    
[ENAME] NVARCHAR(50),
    
[JOB] NVARCHAR(50),
    
[MGR] NVARCHAR(50),
    
[HIREDATE] NVARCHAR(50),
    
[SAL] NVARCHAR(50),
    
[COMM] NVARCHAR(50),
    
[DEPTNO] INT
)
-- important to clean up the memory consumed by the XML Document
EXEC dbo.sp_xml_removedocument @DocumentHandle


COMMIT TRANSACTION
ErrorHandler:
IF @@TRANCOUNT > 0
BEGIN
    
ROLLBACK TRANSACTION
    
PRINT 'Transaction for [dbo].[emp] Rolled Back'
END
GO



另说个题外话,之前想在SQL2005导入文本数据需要打SP2,后来直接用EMS.Data.Import.2007.for.SQL.Server完事,
软件体积才5M。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值