假设:
主表table1
mID 经营业务
-----------------------
1 硬盘
2 键盘
3 显示器
...
子表table2
dID mID 品牌
-----------------------
1 1 西捷
2 1 日立
3 1 IBM
4 2 技嘉
5 2 IBM
6 3 优派
...我想实现一个查询,得到如下的记录:
mID 经营业务 品牌
1 硬盘 西捷,日立,IBM,...
2 键盘 技嘉,IBM,...
3 显示器 优派,...就是子表mID相同的都用逗号分隔,显示出所有经营的品牌,如何写这个视图?谢谢
主表table1
mID 经营业务
-----------------------
1 硬盘
2 键盘
3 显示器
...
子表table2
dID mID 品牌
-----------------------
1 1 西捷
2 1 日立
3 1 IBM
4 2 技嘉
5 2 IBM
6 3 优派
...我想实现一个查询,得到如下的记录:
mID 经营业务 品牌
1 硬盘 西捷,日立,IBM,...
2 键盘 技嘉,IBM,...
3 显示器 优派,...就是子表mID相同的都用逗号分隔,显示出所有经营的品牌,如何写这个视图?谢谢
无论是在sql 2000,还是在 sql 2005 中,都没有提供字符串的聚合函数,
所以,当我们在处理下列要求时,会比较麻烦:
有表tb, 如下:
id value
----- ------
1 aa
1 bb
2 aaa
2 bbb
2 ccc
需要得到结果:
id values
------ -----------
1 aa,bb
2 aaa,bbb,ccc
即, group by id, 求 value 的和(字符串相加)1. 旧的解决方法-- 1. 创建处理函数
CREATE FUNCTION dbo.f_str(@id int)
RETURNS varchar(8000)
AS
BEGIN
DECLARE @r varchar(8000)
SET @r = ''
SELECT @r = @r + ',' + value
FROM tb
WHERE id=@id
RETURN STUFF(@r, 1, 1, '')
END
GO
-- 调用函数SELECt id, values=dbo.f_str(id)
FROM tb
GROUP BY id-- 2. 新的解决方法
-- 示例数据
DECLARE @t TABLE(id int, value varchar(10))
INSERT @t SELECT 1, 'aa'
UNION ALL SELECT 1, 'bb'
UNION ALL SELECT 2, 'aaa'
UNION ALL SELECT 2, 'bbb'
UNION ALL SELECT 2, 'ccc'-- 查询处理
SELECT *
FROM(
SELECT DISTINCT
id
FROM @t
)A
OUTER APPLY(
SELECT
[values]= STUFF(REPLACE(REPLACE(
(
SELECT value FROM @t N
WHERE id = A.id
FOR XML AUTO
), '', ''), 1, 1, '')
)N/*--结果
id values
----------- ----------------
1 aa,bb
2 aaa,bbb,ccc
(2 行受影响)
--*/--各种字符串分函数--3.3.1 使用游标法进行字符串合并处理的示例。
--处理的数据
CREATE TABLE tb(col1 varchar(10),col2 int)
INSERT tb SELECT 'a',1
UNION ALL SELECT 'a',2
UNION ALL SELECT 'b',1
UNION ALL SELECT 'b',2
UNION ALL SELECT 'b',3--合并处理
--定义结果集表变量
DECLARE @t TABLE(col1 varchar(10),col2 varchar(100))参考
insert tb
select 001, 'AA' union all
select 001, 'BB' union all
select 001, 'CC' union all
select 002, 'DD' union all
select 002, 'EE' union all
select 003, 'FF'
go
CREATE FUNCTION dbo.f_tb(@id int)
RETURNS varchar(8000)
AS
BEGIN
DECLARE @str varchar(8000)
SET @str = ''
SELECT @str = @str + ' ' + CardName FROM tb WHERE CardNo=@id
RETURN STUFF(@str, 1, 1, '')
END
GO SELECT CardNo, CardName = dbo.f_tb(CardNo) FROM tb GROUP BY CardNo
drop table tb
drop function dbo.f_tb
go
--2005 XML
if object_id('tb') is not null
drop table tb
create table tb(aa varchar(20),bb varchar(20))
insert into tb select '奥米茄', '地板' union all
select '瓷砖' ,'地板' union all
select '蒙娜丽莎','厨房设备' union all
select '实木复合地板' ,'涂料' select [values]=stuff((select '|'+aa from tb t where bb=tb.bb for xml path('')), 1, 1, ''),bb
from tb
group by bb
/*bb values
-------------------- --------------------
厨房设备 蒙娜丽莎
地板 奥米茄|瓷砖
涂料 实木复合地板(3 行受影响)
*/
无论是在sql 2000,还是在 sql 2005 中,都没有提供字符串的聚合函数,
所以,当我们在处理下列要求时,会比较麻烦:
有表tb, 如下:
id value
----- ------
1 aa
1 bb
2 aaa
2 bbb
2 ccc
需要得到结果:
id values
------ -----------
1 aa,bb
2 aaa,bbb,ccc
即, group by id, 求 value 的和(字符串相加)1. 旧的解决方法-- 1. 创建处理函数
CREATE FUNCTION dbo.f_str(@id int)
RETURNS varchar(8000)
AS
BEGIN
DECLARE @r varchar(8000)
SET @r = ''
SELECT @r = @r + ',' + value
FROM tb
WHERE id=@id
RETURN STUFF(@r, 1, 1, '')
END
GO
-- 调用函数SELECt id, values=dbo.f_str(id)
FROM tb
GROUP BY id-- 2. 新的解决方法
-- 示例数据
DECLARE @t TABLE(id int, value varchar(10))
INSERT @t SELECT 1, 'aa'
UNION ALL SELECT 1, 'bb'
UNION ALL SELECT 2, 'aaa'
UNION ALL SELECT 2, 'bbb'
UNION ALL SELECT 2, 'ccc'-- 查询处理
SELECT *
FROM(
SELECT DISTINCT
id
FROM @t
)A
OUTER APPLY(
SELECT
[values]= STUFF(REPLACE(REPLACE(
(
SELECT value FROM @t N
WHERE id = A.id
FOR XML AUTO
), '<N value="', ','), '"/>', ''), 1, 1, '')
)N/*--结果
id values
----------- ----------------
1 aa,bb
2 aaa,bbb,ccc
(2 行受影响)
--*/
-- -----------t_mac 小编-------------------
--------------------希望有天成为大虾----
-- =========================================IF OBJECT_ID('tb') IS NOT NULL
DROP TABLE tb
GO
CREATE TABLE tb(mID int, 经营业务 varchar(10))
go
insert tb SELECT
1 ,'硬盘' UNION ALL SELECT
2 , '键盘' UNION ALL SELECT
3 , '显示器'
go
IF OBJECT_ID('ta') IS NOT NULL
DROP TABLE ta
GO
CREATE TABLE ta(dID int,mID int, 品牌 varchar(20))
go
insert ta SELECT
1 , 1 , '西捷' UNION ALL SELECT
2 , 1 , '日立' UNION ALL SELECT
3 , 1 , 'IBM' UNION ALL SELECT
4 , 2 , '技嘉' UNION ALL SELECT
5 , 2 , 'IBM' UNION ALL SELECT
6 , 3, '优派'
go
CREATE FUNCTION dbo.f_tb(@id int)
RETURNS varchar(8000)
AS
BEGIN
DECLARE @str varchar(8000)
SET @str = ''
SELECT @str = @str + ',' + 品牌 FROM ta WHERE mID=@id
RETURN STUFF(@str, 1, 1, '')
END
go
select tb.mID , 经营业务,品牌
from(
select mid,dbo.f_tb(mid) as 品牌 from ta group by mid) k
join tb on tb.mID=k.mID
/*
mID 经营业务 品牌
----------- ---------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 硬盘 西捷,日立,IBM
2 键盘 技嘉,IBM
3 显示器 优派*/
-- -----------t_mac 小编-------------------
--------------------希望有天成为大虾----
-- =========================================IF OBJECT_ID('tb') IS NOT NULL
DROP TABLE tb
GO
CREATE TABLE tb(mID int, 经营业务 varchar(10))
go
insert tb SELECT
1 ,'硬盘' UNION ALL SELECT
2 , '键盘' UNION ALL SELECT
3 , '显示器'
go
IF OBJECT_ID('ta') IS NOT NULL
DROP TABLE ta
GO
CREATE TABLE ta(dID int,mID int, 品牌 varchar(20))
go
insert ta SELECT
1 , 1 , '西捷' UNION ALL SELECT
2 , 1 , '日立' UNION ALL SELECT
3 , 1 , 'IBM' UNION ALL SELECT
4 , 2 , '技嘉' UNION ALL SELECT
5 , 2 , 'IBM' UNION ALL SELECT
6 , 3, '优派'
go
select tb.mID , 经营业务,品牌
from(
select mid,STUFF((select ','+品牌 from ta where a.mID=mID for XML path('')),1,1,'') as 品牌 from ta a group by mid) k
join tb on tb.mID=k.mID
/*
mID 经营业务 品牌
----------- ---------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 硬盘 西捷,日立,IBM
2 键盘 技嘉,IBM
3 显示器 优派*/
2005的方法
create table tb1(mid int,经营业务 nvarchar(100))
insert tb1
select 1, '硬盘'
union all select 2, '键盘'
union all select 3, '显示器'
if OBJECT_ID('tb2') is not null drop table tb2
create table tb2(did int,mid int,品牌 nvarchar(10))
insert tb2
select 1, 1, '西捷'
union all select 2, 1, '日立'
union all select 3, 1, 'IBM'
union all select 4, 2, '技嘉'
union all select 5, 2, 'IBM'
union all select 6, 3, '优派'
alter function f_char(@mid int)
returns nvarchar(100)
as
begin
declare @re nvarchar(10)
set @re=N''
select @re=@re+N','+品牌 from tb2 where mid=@mid
return(stuff(@re,1,1,N''))
end
select *,dbo.f_char(mid) as 结果
from tb1
/*
mid 经营业务 结果
1 硬盘 西捷,日立,IBM
2 键盘 技嘉,IBM
3 显示器 优派
*/
stuff((select ','+[品牌] as [text()] from tb2
where tb1.mid=tb2.mid
for xml path('')),1,1,'')
from tb1
group by tb1.mid,tb1.[经营业务]