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 后面加上此列。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM