现在的位置: 首页 > 综合 > 正文

mssql中多表联合查询中去重复

2013年07月20日 ⁄ 综合 ⁄ 共 10567字 ⁄ 字号 评论关闭

IF NOT OBJECT_ID('[a]') IS NULL
    DROP TABLE [a]
GO
CREATE TABLE [a]([id] INT,[name] NVARCHAR(10),[parentid] INT)
INSERT [a]
SELECT 1,'area',0 UNION ALL
SELECT 2,'category',0 UNION ALL
SELECT 3,'north',1 UNION ALL
SELECT 4,'south',1 UNION ALL
SELECT 5,'Shanghai',4 UNION ALL
SELECT 6,'Beijing',3 UNION ALL
SELECT 7,'pudong',5 UNION ALL
SELECT 8,'xuhui',5 UNION ALL
SELECT 9,'chaoyang',6 UNION ALL
SELECT 10,'desk',2 UNION ALL
SELECT 11,'chair',2 UNION ALL
SELECT 12,'bed',2
GO
 
--> 生成测试数据表:b
 
IF NOT OBJECT_ID('[b]') IS NULL
    DROP TABLE [b]
GO
CREATE TABLE [b]([id] INT,[area] INT,[city] INT,[district] NVARCHAR(10))
INSERT [b]
SELECT 1,4,5,'pudong' UNION ALL
SELECT 2,4,5,'xuhui' UNION ALL
SELECT 3,4,6,'chaoyang'
GO
--> 生成测试数据表:c
 
IF NOT OBJECT_ID('[c]') IS NULL
    DROP TABLE [c]
GO
CREATE TABLE [c]([id] INT,[category] INT,[area] INT,[city] INT,[district] INT)
INSERT [c]
SELECT 1,10,4,5,7 UNION ALL
SELECT 2,10,4,5,7 UNION ALL
SELECT 3,11,4,5,8 UNION ALL
SELECT 4,11,3,6,9 UNION ALL
SELECT 5,10,3,6,9
GO
 
-->SQL查询如下:
--SELECT * FROM [a]
--SELECT * FROM [b]
--SELECT * FROM [c]
 
-->SQL查询如下:
select a0.name area,
    a1.name city,
    a2.name district,
    '' address,
    MAX(case a3.name when 'desk' then 数量 else 0 end) 桌子数量,
    MAX(case a3.name when 'chair' then 数量 else 0 end) 椅子数量,
    MAX(case a3.name when 'bed' then 数量 else 0 end) 床数量
from (
    select category,area,city,[district],COUNT(1) 数量 
    from c 
    group by category,area,city,[district]
    ) c  
    join a a0 on a0.id=c.area
    join a a1 on a1.id=c.[city]
    join a a2 on a2.id=c.district
    join a a3 on a3.id=c.category
    left join b on b.area=c.area and c.city=b.city 
group by a0.name,a1.name,a2.name
/*
area       city       district   address 桌子数量        椅子数量        床数量
---------- ---------- ---------- ------- ----------- ----------- -----------
north      Beijing    chaoyang           1           1           0
south      Shanghai   pudong             2           0           0
south      Shanghai   xuhui              0           1           0
 
(3 行受影响)
*/
--处理表重复记录(查询和删除)
/******************************************************************************************************************

************************************
1、Num、Name相同的重复值记录,没有大小关系只保留一条
2、Name相同,ID有大小关系时,保留大或小其中一个记录
整理人:中国风(Roy)
 
日期:2008.06.06
*******************************************************************************************************************

***********************************/
 
--1、用于查询重复处理记录(如果列没有大小关系时2000用生成自增列和临时表处理,SQL2005用row_number函数处理)
 
--> --> (Roy)生成測試數據
 
if not object_id('Tempdb..#T') is null
    drop table #T
Go
Create table #T([ID] int,[Name] nvarchar(1),[Memo] nvarchar(2))
Insert #T
select 1,N'A',N'A1' union all
select 2,N'A',N'A2' union all
select 3,N'A',N'A3' union all
select 4,N'B',N'B1' union all
select 5,N'B',N'B2'
Go
 
 
--I、Name相同ID最小的记录(推荐用1,2,3),方法3在SQl05时,效率高于1、2
方法1:
Select * from #T a where not exists(select 1 from #T where Name=a.Name and ID<a.ID)
 
方法2:
select a.* from #T a join (select min(ID)ID,Name from #T group by Name) b on a.Name=b.Name and a.ID=b.ID
 
方法3:
select * from #T a where ID=(select min(ID) from #T where Name=a.Name)
 
方法4:
select a.* from #T a join #T b on a.Name=b.Name and a.ID>=b.ID group by a.ID,a.Name,a.Memo having count(1)=1 
 
方法5:
select * from #T a group by ID,Name,Memo having ID=(select min(ID)from #T where Name=a.Name)
 
方法6:
select * from #T a where (select count(1) from #T where Name=a.Name and ID<a.ID)=0
 
方法7:
select * from #T a where ID=(select top 1 ID from #T where Name=a.name order by ID)
 
方法8:
select * from #T a where ID!>all(select ID from #T where Name=a.Name)
 
方法9(注:ID为唯一时可用):
select * from #T a where ID in(select min(ID) from #T group by Name)
 
--SQL2005:
 
方法10:
select ID,Name,Memo from (select *,min(ID)over(partition by Name) as MinID from #T a)T where ID=MinID
 
方法11:
 
select ID,Name,Memo from (select *,row_number()over(partition by Name order by ID) as MinID from #T a)T where

MinID=1
 
生成结果:
/*
ID          Name Memo
----------- ---- ----
1           A    A1
4           B    B1
 
(2 行受影响)
*/
 
 
--II、Name相同ID最大的记录,与min相反:
方法1:
Select * from #T a where not exists(select 1 from #T where Name=a.Name and ID>a.ID)
 
方法2:
select a.* from #T a join (select max(ID)ID,Name from #T group by Name) b on a.Name=b.Name and a.ID=b.ID order by

ID
 
方法3:
select * from #T a where ID=(select max(ID) from #T where Name=a.Name) order by ID
 
方法4:
select a.* from #T a join #T b on a.Name=b.Name and a.ID<=b.ID group by a.ID,a.Name,a.Memo having count(1)=1 
 
方法5:
select * from #T a group by ID,Name,Memo having ID=(select max(ID)from #T where Name=a.Name)
 
方法6:
select * from #T a where (select count(1) from #T where Name=a.Name and ID>a.ID)=0
 
方法7:
select * from #T a where ID=(select top 1 ID from #T where Name=a.name order by ID desc)
 
方法8:
select * from #T a where ID!<all(select ID from #T where Name=a.Name)
 
方法9(注:ID为唯一时可用):
select * from #T a where ID in(select max(ID) from #T group by Name)
 
--SQL2005:
 
方法10:
select ID,Name,Memo from (select *,max(ID)over(partition by Name) as MinID from #T a)T where ID=MinID
 
方法11:
select ID,Name,Memo from (select *,row_number()over(partition by Name order by ID desc) as MinID from #T a)T where

MinID=1
 
生成结果2:
/*
ID          Name Memo
----------- ---- ----
3           A    A3
5           B    B2
 
(2 行受影响)
*/
--分组取其中某字段最小,去重复
if object_id('[tb]') is not null drop table [tb]
go 
create table [tb]([EID] varchar(2),[OID] varchar(2),[Value] int)
insert [tb]
select 'E1','O1',4 union all
select 'E2','O2',16 union all
select 'E3','O1',5 union all
select 'E4','O2',8 union all
select 'E5','O1',3 union all
select 'E6','O3',9
 
select t1.* from tb t1
where  EID  = (
    select top 1 t2. EID  from tb t2 
    where t2.Value = (
        select min(t3.Value) from tb t3
        where t2.EID=t3.EID  
    ) and t1.OID=t2.OID 

and  t1.EID in ('E1','E2','E4')
--按某一字段分组取最大(小)值所在行的数据
--(爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开) 2007-10-23于浙江杭州)
/*
数据如下:
name val memo
a    2   a2(a的第二个值)
a    1   a1--a的第一个值
a    3   a3:a的第三个值
b    1   b1--b的第一个值
b    3   b3:b的第三个值
b    2   b2b2b2b2
b    4   b4b4
b    5   b5b5b5b5b5
*/
--创建表并插入数据:
create table tb(name varchar(10),val int,memo varchar(20))
insert into tb values('a',    2,   'a2(a的第二个值)')
insert into tb values('a',    1,   'a1--a的第一个值')
insert into tb values('a',    3,   'a3:a的第三个值')
insert into tb values('b',    1,   'b1--b的第一个值')
insert into tb values('b',    3,   'b3:b的第三个值')
insert into tb values('b',    2,   'b2b2b2b2')
insert into tb values('b',    4,   'b4b4')
insert into tb values('b',    5,   'b5b5b5b5b5')
go
 
--一、按name分组取val最大的值所在行的数据。
--方法1:
select a.* from tb a where val = (select max(val) from tb where name = a.name) order by a.name
--方法2:
select a.* from tb a where not exists(select 1 from tb where name = a.name and val > a.val)
--方法3:
select a.* from tb a,(select name,max(val) val from tb group by name) b where a.name = b.name and a.val = b.val

order by a.name
--方法4:
select a.* from tb a inner join (select name , max(val) val from tb group by name) b on a.name = b.name and a.val =

b.val order by a.name
--方法5
select a.* from tb a where 1 > (select count(*) from tb where name = a.name and val > a.val ) order by a.name
/*
name       val         memo                 
---------- ----------- -------------------- 
a          3           a3:a的第三个值
b          5           b5b5b5b5b5
*/
 
--二、按name分组取val最小的值所在行的数据。
--方法1:
select a.* from tb a where val = (select min(val) from tb where name = a.name) order by a.name
--方法2:
select a.* from tb a where not exists(select 1 from tb where name = a.name and val < a.val)
--方法3:
select a.* from tb a,(select name,min(val) val from tb group by name) b where a.name = b.name and a.val = b.val

order by a.name
--方法4:
select a.* from tb a inner join (select name , min(val) val from tb group by name) b on a.name = b.name and a.val =

b.val order by a.name
--方法5
select a.* from tb a where 1 > (select count(*) from tb where name = a.name and val < a.val) order by a.name
/*
name       val         memo                 
---------- ----------- -------------------- 
a          1           a1--a的第一个值
b          1           b1--b的第一个值
*/
 
--三、按name分组取第一次出现的行所在的数据。
select a.* from tb a where val = (select top 1 val from tb where name = a.name) order by a.name
/*
name       val         memo                 
---------- ----------- -------------------- 
a          2           a2(a的第二个值)
b          1           b1--b的第一个值
*/
 
--四、按name分组随机取一条数据。
select a.* from tb a where val = (select top 1 val from tb where name = a.name order by newid()) order by a.name
/*
name       val         memo                 
---------- ----------- -------------------- 
a          1           a1--a的第一个值
b          5           b5b5b5b5b5
*/
 
--五、按name分组取最小的两个(N个)val
select a.* from tb a where 2 > (select count(*) from tb where name = a.name and val < a.val ) order by a.name,a.val
select a.* from tb a where val in (select top 2 val from tb where name=a.name order by val) order by a.name,a.val
select a.* from tb a where exists (select count(*) from tb where name = a.name and val < a.val having Count(*) < 2)

order by a.name,a.val
/*
name       val         memo                 
---------- ----------- -------------------- 
a          1           a1--a的第一个值
a          2           a2(a的第二个值)
b          1           b1--b的第一个值
b          2           b2b2b2b2
*/
 
--六、按name分组取最大的两个(N个)val
select a.* from tb a where 2 > (select count(*) from tb where name = a.name and val > a.val ) order by a.name,a.val
select a.* from tb a where val in (select top 2 val from tb where name=a.name order by val desc) order by

a.name,a.val
select a.* from tb a where exists (select count(*) from tb where name = a.name and val > a.val having Count(*) < 2)

order by a.name , a.val
/*
name       val         memo                 
---------- ----------- -------------------- 
a          2           a2(a的第二个值)
a          3           a3:a的第三个值
b          4           b4b4
b          5           b5b5b5b5b5
*/
--七,如果整行数据有重复,所有的列都相同。
/*
数据如下:
name val memo
a    2   a2(a的第二个值)
a    1   a1--a的第一个值
a    1   a1--a的第一个值
a    3   a3:a的第三个值
a    3   a3:a的第三个值
b    1   b1--b的第一个值
b    3   b3:b的第三个值
b    2   b2b2b2b2
b    4   b4b4
b    5   b5b5b5b5b5
*/
--在sql server 2000中只能用一个临时表来解决,生成一个自增列,先对val取最大或最小,然后再通过自增列来取数据。
--创建表并插入数据:
create table tb(name varchar(10),val int,memo varchar(20))
insert into tb values('a',    2,   'a2(a的第二个值)')
insert into tb values('a',    1,   'a1--a的第一个值')
insert into tb values('a',    1,   'a1--a的第一个值')
insert into tb values('a',    3,   'a3:a的第三个值')
insert into tb values('a',    3,   'a3:a的第三个值')
insert into tb values('b',    1,   'b1--b的第一个值')
insert into tb values('b',    3,   'b3:b的第三个值')
insert into tb values('b',    2,   'b2b2b2b2')
insert into tb values('b',    4,   'b4b4')
insert into tb values('b',    5,   'b5b5b5b5b5')
go
 
select * , px = identity(int,1,1) into tmp from tb
 
select m.name,m.val,m.memo from
(
  select t.* from tmp t where val = (select min(val) from tmp where name = t.name)
) m where px = (select min(px) from
(
  select t.* from tmp t where val = (select min(val) from tmp where name = t.name)
) n where n.name = m.name)
 
drop table tb,tmp
 
/*
name       val         memo
---------- ----------- --------------------
a          1           a1--a的第一个值
b          1           b1--b的第一个值
 
(2 行受影响)
*/
--在sql server 2005中可以使用row_number函数,不需要使用临时表。
--创建表并插入数据:
create table tb(name varchar(10),val int,memo varchar(20))
insert into tb values('a',    2,   'a2(a的第二个值)')
insert into tb values('a',    1,   'a1--a的第一个值')
insert into tb values('a',    1,   'a1--a的第一个值')
insert into tb values('a',    3,   'a3:a的第三个值')
insert into tb values('a',    3,   'a3:a的第三个值')
insert into tb values('b',    1,   'b1--b的第一个值')
insert into tb values('b',    3,   'b3:b的第三个值')
insert into tb values('b',    2,   'b2b2b2b2')
insert into tb values('b',    4,   'b4b4')
insert into tb values('b',    5,   'b5b5b5b5b5')
go
 
select m.name,m.val,m.memo from
(
  select * , px = row_number() over(order by name , val) from tb
) m where px = (select min(px) from
(
  select * , px = row_number() over(order by name , val) from tb
) n where n.name = m.name)
 
drop table tb
 
/*
name       val         memo
---------- ----------- --------------------
a          1           a1--a的第一个值
b          1           b1--b的第一个值
 
(2 行受影响)
*/

抱歉!评论已关闭.