sql多行多列重复

在sql的查询中我们会遇到查询的结果比如这样的:

查询这张表的sql语句:

select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_USERINFOR u left join BASE_USERROLE ur on u.USERID=ur.USER_ID
left join BASE_ROLEINFOR r on r.ROLE_ID=ur.ROLE_ID

就拿钱三行来说就一个ROLE_NAME不一样其他的列的数值都是一样的难道我们就要这样的结果,就算我们要这样的结果但是当我们想要在前台这样显示一个页面的时候我们怎么办

这样的话我们该怎么去查询该怎么组合,把它分开来查询当然也能解决,但是想想那样我们要查询多少次要连接数据库对少次。

这样想想就觉得很麻烦当然想想也知道这样做肯定是降低了程序的执行效率。所以我们就应该想另一种方法怎样查询一次就可以变成这种效果。

想想看我们查询的结果是一张表那我们就看这张表的XML文件的组成是什么样的

查看表的组成的XML文件的sql语句:

select * from (select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_USERINFOR u left join BASE_USERROLE ur on u.USERID=ur.USER_ID
left join BASE_ROLEINFOR r on r.ROLE_ID=ur.ROLE_ID) t for XML path

查出表的XML文件的组成

想想看如果我们可以替换XML文件的组成的话我们是不是就可以改变表的结构了

我们先看一个简单的表,多行的重复是怎么合并的

select * from table1

查询结果:

看看这样的一个简单的表我们是怎样合并相同的列的

第一步:当然是查看表的XML文件看看表是怎样组成的

select * from table1 for XML path;

查询的结果:

<row>
  <uid>1</uid>
  <rname>管理员</rname>
</row>
<row>
  <uid>1</uid>
  <rname>店主</rname>
</row>
<row>
  <uid>1</uid>
  <rname>买家</rname>
</row>
<row>
  <uid>2</uid>
  <rname>店主</rname>
</row>
<row>
  <uid>2</uid>
  <rname>店主</rname>
</row>

根据查询的结果我们不难看出表的组成的简单结构,可能是数据库自己定义好的也可能是我们在查询的时候自动生成的,不管是定义好的还是自己生成的我们先看看是否可以改变表的组成结构如果可以的话我们是不是就可以改变我们想要的结构呢?

第二步:改变表的组成结构

select * from table1 for XML path;

还是这句语句既然可以查询表的XML文件组成那是否可以改变表的XML文件的组成呢。试试就知道了(程序就是你想的再多不如你敲几行代码一试)

select * from table1 for XML path(‘a‘);

我们这样写语句看看我们的表的XML文件的组成变成了什么样:

<a>
  <uid>1</uid>
  <rname>管理员</rname>
</a>
<a>
  <uid>1</uid>
  <rname>店主</rname>
</a>
<a>
  <uid>1</uid>
  <rname>买家</rname>
</a>
<a>
  <uid>2</uid>
  <rname>店主</rname>
</a>
<a>
  <uid>2</uid>
  <rname>店主</rname>
</a>

比较两次的查询结果看看我们的表的XML文件发生了什么变化:

select * from table1 for XML path;

XML文件:
<row>
  <uid>1</uid>
  <rname>管理员</rname>
</row>

select * from table1 for XML path(‘a‘);

XML文件的组成:
<a>
  <uid>1</uid>
  <rname>管理员</rname>
</a>

可以产出<row>标签变成了<a>,那么我们把path(‘a‘)中的a去掉会变成什么样:

查询语句:
select * from table1 for XML path(‘‘);
查询结果:
<uid>1</uid>
<rname>管理员</rname>
<uid>1</uid>
<rname>店主</rname>
<uid>1</uid>
<rname>买家</rname>
<uid>2</uid>
<rname>店主</rname>
<uid>2</uid>
<rname>店主</rname>

比较两次的查询结果:

select * from table1 for XML path(‘a‘);
查询结果:
<a>
  <uid>1</uid>
  <rname>管理员</rname>
</a>

select * from table1 for XML path(‘‘);
查询结果:
<uid>1</uid>
<rname>管理员</rname>

可以看出<a>去掉了,我们想要的是什么是用户的角色那我们就要角色看看:

第三步:去掉多余的行

select rname from table1 for XML path(‘‘);
查询的结果:
<rname>管理员</rname>
<rname>店主</rname>
<rname>买家</rname>
<rname>店主</rname>
<rname>店主</rname>

当然这仍然不是我们想要的结果我们想要的里面的数据,所以我们需要去掉<rname>标签:

第四步:去掉不要的标签:

select rname+‘,‘ from table1 for XML path(‘‘);
查询的结果:
管理员,店主,买家,店主,店主,

这就是我们想要的结果了,结果是拿到了但是我们想要的是什么效果啊,先看看我们们想要的表是什么样的

这是我们想要的表,但是怎么组成呢?

再看看我们原来的表:

想想看我们应该把这张表变形:

uid是多行的那我们就先不看rname这一列,我们先进行分组:

第五步:分组

根据uId进行分组

select uid from table1 group by uid

结果:

好,最重要的一步来了:

我们怎么把管理员,店主,买家,放在对应uid为1的一行,怎么把店主,店主,放在对应的uid为2的一行后面

第六步:合并:

也就是在这个表的后面添加一列。这样就简单了

select uid,(这一列就是rname)from table1 t group by uid;

那我们就增加一列:

上面我们的查询时查询所有的列现在我们加上条件:

select rname+‘,‘ from table1 t1 where t1.uid=1 for XML path(‘‘);

查询结果:

管理员,店主,买家,

这不就是我们想要的嘛,只要把条件改变一下就可以了嘛,现在我们进行合并也就是增加一列。

select uid,(这一列就是rname)from table1 t group by uid;
增加rname这一列:
select uid,(select rname+‘,‘ from table1 t1 where t1.uid=t.uid for XML path(‘‘)) as rname from table1 t group by uid;

我们看看这个语句的查询结果是什么?

select uid,(select rname+‘,‘ from table1 t1 where t1.uid=t.uid for XML path(‘‘)) as rolenames from table1 t group by uid;

结果:

这就是我们想要的结果了。

好了简单表的组成会了我们来点复杂的

继续完成我们刚开始提出的问题:

合成这张表试试看

查询语句:

select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_USERINFOR u left join BASE_USERROLE ur on u.USERID=ur.USER_ID
left join BASE_ROLEINFOR r on r.ROLE_ID=ur.ROLE_ID

我们该怎么合并这张表呢。仔细想想看其实道理是一样的我们直接把这张表当让是table1表,在往刚刚的sql语句一套不就行了

看看刚才的sql语句:

select uid,(select rname+‘,‘ from table1 t1 where t1.uid=t.uid for XML path(‘‘)) as rolenames from table1 t group by uid;

看看哪里用到了table1我们改变一下就行了
select uid,(select rname+‘,‘ from (table1表) t1 where t1.uid=t.uid for XML path(‘‘)) as rolenames from (table1表) t group by uid;

再根据我们的表看一看也就是改变一下查询的列的问题:

我们改变一下

select USERID,(select t.ROLE_NAME+‘,‘ from (table1表))t where t.USERID=t1.USERID for XML path(‘‘)) as RoleName from(table1表)t1  group by USERID,TrueName,USERNAME

好了把我们的“table1表”放进去,执行一下看看什么结果

select USERID,(select t.ROLE_NAME+‘,‘ from
(select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_USERINFOR u
left join BASE_USERROLE ur on u.USERID=ur.USER_ID
left join BASE_ROLEINFOR r on r.ROLE_ID=ur.ROLE_ID) t where t.USERID=t1.USERID for XML path(‘‘)) as RoleName from
(select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_USERINFOR u
left join BASE_USERROLE ur on u.USERID=ur.USER_ID
left join BASE_ROLEINFOR r on r.ROLE_ID=ur.ROLE_ID) t1  group by USERID

查询结果:

可是跟上面的表比较一下我们的表少了几列所以我们要把少的几列加上:

select USERID,TrueName,USERNAME,(select t.ROLE_NAME+‘,‘ from
(select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_USERINFOR u
left join BASE_USERROLE ur on u.USERID=ur.USER_ID
left join BASE_ROLEINFOR r on r.ROLE_ID=ur.ROLE_ID) t where t.USERID=t1.USERID for XML path(‘‘)) as RoleName from
(select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_USERINFOR u
left join BASE_USERROLE ur on u.USERID=ur.USER_ID
left join BASE_ROLEINFOR r on r.ROLE_ID=ur.ROLE_ID) t1  group by USERID,TrueName,USERNAME

看看查询的结果是不是我们想要的

在这里一定要注意一下group by 后面的语句,虽然我们写那么多的分组条件就只是第一个条件及作用我们仍然要写因为只有这样我们在查询的时候才可以去查询想要的列。

所以当你想要的查询其他的列的时候你就需要在group by 后面加上此列。

时间: 2024-10-13 20:50:47

sql多行多列重复的相关文章

SQL Server 行转列

语法: PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )AS P 完整语法: table_source PIVOT( 聚合函数(value_column) FOR pivot_column IN(<column_list>) ) UNPIVOT用于将列明转为列值(即列转行),在SQL Server 2000可以用UNION来实现 完整语法: table

做图表统计你需要掌握SQL Server 行转列和列转行

说在前面 做一个数据统计和分析的项目,每天面对着各种数据,经过存储过程从源表计算汇总后需要写入中间结果表以提高数据使用效率,那么此时就需要用到行转列和列转行. 1.列转行 数据经过计算加工后会直接生成前端图表需要的数据源,但是程序里又需要把该数据经过列转行写入中间表中,下次再查询该数据时直接从中间表查询数据. 1.1 列换行语法 table_source UNPIVOT( value_column FOR pivot_column IN(<column_list>) ) 1.2  行转列案例

sql的行转列(PIVOT)与列转行(UNPIVOT)

在做数据统计的时候,行转列,列转行是经常碰到的问题.case when方式太麻烦了,而且可扩展性不强,可以使用 PIVOT,UNPIVOT比较快速实现行转列,列转行,而且可扩展性强 一.行转列 1.测试数据准备 CREATE TABLE [StudentScores] ( [UserName] NVARCHAR(20), --学生姓名 [Subject] NVARCHAR(30), --科目 [Score] FLOAT, --成绩 ) INSERT INTO [StudentScores] SE

sql server 行转列(转载)

SQL Server中行列转换 Pivot UnPivot PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )AS P 完整语法: table_source PIVOT( 聚合函数(value_column) FOR pivot_column IN(<column_list>) ) UNPIVOT用于将列明转为列值(即列转行),在SQL Server 2

sql的行转列和列转行

一.行转列 1.测试数据准备 CREATE TABLE [StudentScores] ( [UserName] NVARCHAR(20), --学生姓名 [Subject] NVARCHAR(30), --科目 [Score] FLOAT, --成绩 ) INSERT INTO [StudentScores] SELECT '张三', '语文', 80 INSERT INTO [StudentScores] SELECT '张三', '数学', 90 INSERT INTO [StudentS

SQL Server 行转列,列转行

一.多行转成一列(并以","隔开) 表名:A 表数据: 想要的查询结果: 查询语句: SELECT name , value = ( STUFF(( SELECT ',' + value FROM A WHERE name = Test.name FOR XML PATH('') ), 1, 1, '') ) FROM A AS Test GROUP BY name; PS:STUFF语句就是为了去掉第一个[逗号] 附STUFF用法:(从原字符的第二个开始共三个字符替换为后面的字符)

Sql 动态行转列 pivot

最近朋友有个需求:将产品中为“期刊”的书品以行转列的形式展现,同时需要关联工单主表及工单明细表,显示内容为,工单号.操作日期.产品名称及数量,由于期刊的产品数量较多,静态的虽然可以实现,但不利于后续内容的添加,就想着如何能以动态的形式展现,自动拼接sql语句处理,具体实现过程如下. 产品信息表需用到的字段内容: select ProductCode,Name from ComProduct where ProductType ='20' 工单需要用到的内容: select JobNo,Produ

SQL Server行转列

在很多情况下需要查询出来的数据进行行转列,看如下的例子,#t是一个临时表,可以换成真实存在的表: --头部信息,这部分不参与行转列DECLARE @SqlText NVARCHAR(4000)='SELECT DeviceName 货机名称, DeviceAddress 货机地址,CONVERT(VARCHAR(10), ReplenishmentCreatedDate, 20) 时间, ' -- SQL头部分 SELECT --行转列如下:可以重命名字段名,列头用其中一个列生成,列信息用另一个

SQL server 行转列 列转行

1.简单案例 create database Hang go use Hang create table Students ( Name varchar(50), Kemu varchar(50), sor int ) insert into Students values('张三','语文',8888) insert into Students values('张三','语文',85) insert into Students values('张三','数学',75) insert into