数据资料:tb:
id iQuantity
----------------
1 100
2 130 tbs:
id Cname iQuantity
---------------------------
1 A 10
2 B 8
1 C 10
1 F 10
2 F 15注:两表以ID字段作关连要求结果是:
id iQuantity CNAME Already remaining
------------------------------------------------
1 100 A,C,F 30 70
2 130 B,F 23 107 id
GO
SET ANSI_NULLS ON
GO
--得到字符串学生ID
ALTER FUNCTION [GetStrID]
(
--班级号
@ID int
)
RETURNS nvarchar(100)
AS
BEGIN
DECLARE @Name nvarchar(100)
SELECT @Name = ''
SELECT @Name = @Name+ID FROM 班级表 WHERE ID=-@ID
RETURN @NameEND
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO 要写一个得到字符串
合并分拆表数据 整理人:中国风(Roy) 日期:2008.06.06
******************************************************************************************************************************************************/ --> --> (Roy)生成測試數據 if not object_id('Tab') is null
drop table Tab
Go
Create table Tab([Col1] int,[Col2] nvarchar(1))
Insert Tab
select 1,N'a' union all
select 1,N'b' union all
select 1,N'c' union all
select 2,N'd' union all
select 2,N'e' union all
select 3,N'f'
Go 合并表: SQL2000用函数: go
if object_id('F_Str') is not null
drop function F_Str
go
create function F_Str(@Col1 int)
returns nvarchar(100)
as
begin
declare @S nvarchar(100)
select @S=isnull(@S+',','')+Col2 from Tab where Col1=@Col1
return @S
end
go
Select distinct Col1,Col2=dbo.F_Str(Col1) from Tab go SQL2005用XML: 方法1: select
a.Col1,Col2=stuff(b.Col2.value('/R[1]','nvarchar(max)'),1,1,'')
from
(select distinct COl1 from Tab) a
Cross apply
(select COl2=(select N','+Col2 from Tab where Col1=a.COl1 For XML PATH(''), ROOT('R'), TYPE))b 方法2: select
a.Col1,COl2=replace(b.Col2.value('/Tab[1]','nvarchar(max)'),char(44)+char(32),char(44))
from
(select distinct COl1 from Tab) a
cross apply
(select Col2=(select COl2 from Tab where COl1=a.COl1 FOR XML AUTO, TYPE)
.query(' <Tab>
{for $i in /Tab[position() <last()]/@COl2 return concat(string($i),",")}
{concat("",string(/Tab[last()]/@COl2))}
</Tab>')
)b SQL05用CTE: ;with roy as(select Col1,Col2,row=row_number()over(partition by COl1 order by COl1) from Tab)
,Roy2 as
(select COl1,cast(COl2 as nvarchar(100))COl2,row from Roy where row=1
union all
select a.Col1,cast(b.COl2+','+a.COl2 as nvarchar(100)),a.row from Roy a join Roy2 b on a.COl1=b.COl1 and a.row=b.row+1)
select Col1,Col2 from Roy2 a where row=(select max(row) from roy where Col1=a.COl1) order by Col1 option (MAXRECURSION 0)
生成结果:
/*
Col1 COl2
----------- ------------
1 a,b,c
2 d,e
3 f (3 行受影响)
*/
--参考
拆分表:--> --> (Roy)生成測試數據
if not object_id('Tab') is null
drop table Tab
Go
Create table Tab([Col1] int,[COl2] nvarchar(5))
Insert Tab
select 1,N'a,b,c' union all
select 2,N'd,e' union all
select 3,N'f'
Go--SQL2000用辅助表:
if object_id('Tempdb..#Num') is not null
drop table #Num
go
select top 100 ID=Identity(int,1,1) into #Num from syscolumns a,syscolumns b
Select
a.Col1,COl2=substring(a.Col2,b.ID,charindex(',',a.Col2+',',b.ID)-b.ID)
from
Tab a,#Num b
where
charindex(',',','+a.Col2,b.ID)=b.ID --也可用 substring(','+a.COl2,b.ID,1)=','
--2000不使用辅助表
Select
a.Col1,COl2=substring(a.Col2,b.number,charindex(',',a.Col2+',',b.number)-b.number)
from
Tab a join master..spt_values b
ON B.type='p' AND B.number BETWEEN 1 AND LEN(A.col2)
where
substring(','+a.COl2,b.number,1)=','
SQL2005用Xml:select
a.COl1,b.Col2
from
(select Col1,COl2=convert(xml,'<root><v>'+replace(COl2,',','</v><v>')+'</v></root>') from Tab)a
outer apply
(select Col2=C.v.value('.','nvarchar(100)') from a.COl2.nodes('/root/v')C(v))b
SQL05用CTE:;with roy as
(select Col1,COl2=cast(left(Col2,charindex(',',Col2+',')-1) as nvarchar(100)),Split=cast(stuff(COl2+',',1,charindex(',',Col2+','),'') as nvarchar(100)) from Tab
union all
select Col1,COl2=cast(left(Split,charindex(',',Split)-1) as nvarchar(100)),Split= cast(stuff(Split,1,charindex(',',Split),'') as nvarchar(100)) from Roy where split>''
)
select COl1,COl2 from roy order by COl1 option (MAXRECURSION 0)生成结果:
/*
Col1 COl2
----------- -----
1 a
1 b
1 c
2 d
2 e
3 f
*/
if object_id('[tb]') is not null drop table [tb]
go
create table [tb]([id] int,[iQuantity] int)
insert [tb]
select 1,100 union all
select 2,130--> 测试数据:[tbs]
if object_id('[tbs]') is not null drop table [tbs]
go
create table [tbs]([id] int,[Cname] varchar(1),[iQuantity] int)
insert [tbs]
select 1,'A',10 union all
select 2,'B',8 union all
select 1,'C',10 union all
select 1,'F',10 union all
select 2,'F',15--------------------------------查询开始------------------------------
select * from [tb] a,
(
select[id], [Cname]=stuff((select ','+[Cname] from [tbs] t where id=[tbs].id for xml path('')), 1, 1, ''),sum([iQuantity]) as [iQuantity]
from [tbs]
group by [id]
) b
where a.id=b.id
/*
id iQuantity id Cname iQuantity
----------- ----------- ----------- --------------------------------
1 100 1 A,C,F 30
2 130 2 B,F 23(2 行受影响)
*/
CREATE TABLE #tb
(
id int,
iQuantity int
)CREATE TABLE #tbs
(
id int,
cname varchar,
iQuantity int
)INSERT INTO #tb
SELECT 1,100 UNION ALL
SELECT 2,130INSERT INTO #tbs
SELECT 1,'A',10 UNION ALL
SELECT 2,'B',8 UNION ALL
SELECT 1,'C',10 UNION ALL
SELECT 1,'F',10 UNION ALL
SELECT 2,'F',15
SELECT
a.id,
a.iQuantity,
stuff((select ',' + cname from #tbs where id = a.id for xml path('')),1,1,''),
sum(b.iQuantity),
a.iQuantity-sum(b.iQuantity)
FROM
#tb a join
#tbs b ON a.ID = b.ID
GROUP BY
a.id,
a.iQuantity
1 100 A,C,F 30 70
2 130 B,F 23 107
IF OBJECT_ID('tb') IS NOT NULL DROP TABLE tb
GO
CREATE TABLE tb
(
id int identity,
iQuantity int,
CONSTRAINT PK_TB PRIMARY KEY (id)
)
GO
INSERT TB
SELECT 100 union
select 130
go
IF OBJECT_ID('tbs') IS NOT NULL DROP TABLE tbs
GO
CREATE TABLE tbs
(
id int ,
Cname varchar(10),
iQuantity int
)
GO
INSERT tbs
SELECT 1,'A',10 union all
SELECT 2,'B',8 union all
SELECT 1,'C',10 union all
SELECT 1,'F',10 union all
SELECT 2,'F',15
go
create function dbo.f_str(@id int) returns varchar(100)
as
begin
declare @str varchar(1000)
set @str = ''
select @str = @str + ',' + Cname from tbs where id = @id
set @str = right(@str , len(@str) - 1)
return @str
end
go--查询
select a.id,a.iQuantity,dbo.f_str(a.id) CNAME,
sum(b.iQuantity) Already,a.iQuantity-sum(b.iQuantity) remaining
from tb a join tbs b on a.id=b.id
group by a.id,a.iQuantity
--结果
/*(2 行受影响)(5 行受影响)
id iQuantity CNAME Already remaining
----------- ----------- ---------------------------------------------------------------------------------------------------- ----------- -----------
1 100 A,C,F 30 70
2 130 B,F 23 107(2 行受影响)
*/
其实不光是今天,呆久了就发现,大部分都是问 行转列、字符连接/拆分、解BOM、分类汇总 这样的问题,应该对这几个问题搞个置顶贴,大家看过后,再问。
if object_id('[tb]') is not null drop table [tb]
go
create table [tb]([id] int,[iQuantity] int)
insert [tb]
select 1,100 union all
select 2,130--> 测试数据:[tbs]
if object_id('[tbs]') is not null drop table [tbs]
go
create table [tbs]([id] int,[Cname] varchar(1),[iQuantity] int)
insert [tbs]
select 1,'A',10 union all
select 2,'B',8 union all
select 1,'C',10 union all
select 1,'F',10 union all
select 2,'F',15--------------------------------查询开始------------------------------
select *,remaining=iQuantity - Already from [tb] a,
(
select[id], [Cname]=stuff((select ','+[Cname] from [tbs] t where id=[tbs].id for xml path('')), 1, 1, ''),sum([iQuantity]) as Already
from [tbs]
group by [id]
) b
where a.id=b.id
/*
id iQuantity id Cname Already remaining
----------- ----------- ----------- -------- ----------- ----------
1 100 1 A,C,F 30 70
2 130 2 B,F 23 107
(2 行受影响)
*/
if object_id('[ta]') is not null drop table [ta]
go
create table [ta] (id int,iQuantity int)
insert into [ta]
select 1,100 union all
select 2,130
--> 测试数据: [tbs:]
if object_id('[tbs]') is not null drop table [tbs]
go
create table [tbs] (id int,Cname varchar(1),iQuantity int)
insert into [tbs]
select 1,'A',10 union all
select 2,'B',8 union all
select 1,'C',10 union all
select 1,'F',10 union all
select 2,'F',15if object_id('f_str') is not null drop function f_str
go
create function f_str(@i int)
returns varchar(20)
as
begin
declare @s varchar(20)
select @s=isnull(@s+',','')+cname from tbs where id=@i
return @s
end
go select a.id,a.iQuantity,b.cname,b.already,remaining=a.iQuantity-b.already
from ta a
join (
select id,Already=sum(iQuantity),cname=dbo.f_str(id)
from tbs group by id
) b
on a.id=b.id
id iQuantity cname already remaining
----------- ----------- -------------------- ----------- -----------
1 100 A,C,F 30 70
2 130 B,F 23 107(2 行受影响)