sqlserver -- 學習筆記(八)體驗charindex、stuff 和 for xml path在實際問題中的應用及幾個問題的探討


  • 寫在前面

之前做了個微信端顧客掃碼評價員工的功能,除了打分數,還可以打標簽。

需要統計分數和統計各個員工每種標簽被點擊的次數。

后來加了個要求,需要查看客戶對某個員工一次服務所打出的標簽組合。

    在不修改表設計的前提下,解決這個問題!

 

     實際開發時數據表設計需要考慮的東西比較多,而這篇分享主要是寫函數的應用,為了方便看,所以表設計簡化了,下面兩個表的設計也都是簡化過的。

 

   數據表設計如下(只列出部分要用到的字段):

   測試數據格式如下:

         

 

  備注說明:

(1)tagIDs的值1,2,表示“態度非常好,笑容甜美”。

(2)表2的每1條記錄代表客戶的每1次評價。

 所以,問題可以簡化為查詢表2中id=2的中文標簽組合,返回“態度非常好,笑容甜美”。

 

在解決問題之前,先來認識幾個函數!!!

 

--------@_@! 知識點一 ---------------------------------------------------------------------------

  charindex函數

  charindex函數返回字符或者字符串在另一個字符串中的起始位置。

  charindex函數調用方法如下:CHARINDEX ( expression1 , expression2 [ , start_location ] )

--------------------------------------------------------------------------------------------------

語句示例:

select charindex('1', '1,2,3') as position 
select charindex('world', 'hello,world') as position 
select charindex('sql', 'hello,world') as position 

在sqlserver中運行后的結果為:

1
7
0

可見,當experssion1與expression2沒有匹配時返回0。

 

--------@_@??----------------------------------------------------------------------------

  疑問:這樣的寫法是正確的嗎?

  提問:如果tagIDs='1,2,3,16',那么id=6的話,按上面的寫法是不是也算是包含在里面?

-----------------------------------------------------------------------------------------

 sqlserver中執行下面語句:

select 'found' as flag where charindex(ltrim(6),'1,2,3,16')>0

輸出結果為:found

 

=_=|| 那么該如何處理使得6不會跟16里面的6匹配上呢?

當6變成“,6,”時,“,6,”就不會和“1,2,3,16”中的6匹配上了!

那么“,6,”和“1,6”中的6也匹配不上了!

把母字符串也進行修改也在前后都加上“,”

這樣“6”和“,1,6,”、“,6,7,8,”中的6都可以匹配上了!同時也跟“,1,2,3,16,”中16的6匹配不上。

select 'notFound' as flag where charindex(','+ltrim(6)+',',','+'1,2,3,16'+',')=0

查詢結果為:notFound。 問題解決~

 

--------@_@ 知識點二 -----------------------------------------------------------------------

  STUFF ( character_expression , start , length ,character_expression ) 

  參數說明:

    character_expression :一個字符數據表達式。character_expression 可以是常量、變量,也可以是字符列或二進制數據列。

  start :一個整數值,指定刪除和插入的開始位置。如果 start 或 length 為負,則返回空字符串。 如果 start 比第一個character_expression 長,則返回空字符串。start 可以是 bigint 類型。

  length :一個整數,指定要刪除的字符數。如果 length 比第一個 character_expression 長,則最多刪除到最后一個character_expression 中的最后一個字符。length 可以是 bigint 類型。

  返回類型 :如果 character_expression 是受支持的字符數據類型,則返回字符數據。如果 character_expression 是一個受支持的 binary 數據類型,則返回二進制數據。

 

  備注 :

  如果開始位置或長度值是負數,或者如果開始位置大於第一個字符串的長度,將返回空字符串。

  如果要刪除的長度大於第一個字符串的長度,將刪除到第一個字符串中的第一個字符。 

  如果結果值大於返回類型支持的最大值,則產生錯誤。

------------------------------------------------------------------------------------------------

   語句示例:

select stuff('abcdef', 2,4,'123') --將'abcdef'從第2個開始,連續刪掉4個字符,然后將'123'插入

 執行結果:

a123f

 

----------@_@ 知識點三 ----------------------------------------------------------------

  For xml path: 用於將查詢結果集以XML形式顯示

------------------------------------------------------------------------------------------

我們用下面這張表的數據來體驗下:

 

示例語句:

select id, tagName from tb_tagList for xml path  

執行結果:

<row>
  <id>1</id>
  <tagName>態度非常好</tagName>
</row>
<row>
  <id>2</id>
  <tagName>笑容甜美</tagName>
</row>
<row>
  <id>3</id>
  <tagName>效率很高</tagName>
</row>
<row>
  <id>5</id>
  <tagName>對人熱情</tagName>
</row>
<row>
  <id>6</id>
  <tagName>為他人着想</tagName>
</row>
<row>
  <id>7</id>
  <tagName>細心負責</tagName>
</row>

如果想改成用“,”,修改語句如下:

SELECT tagName + ',' FROM tb_tagList FOR XML PATH('')

執行結果:

態度非常好,笑容甜美,效率很高,對人熱情,為他人着想,細心負責,

會發現最后面還有個逗號!

如果想把它去掉,可以修改語句,將逗號加在每個標簽的前面,然后stuff函數把第一個逗號替換為空字符串。

將 tagName + ',' 改為  ',' + tagName 

修改語句

SELECT tagNames = (stuff (( select ','+tagName  FROM tb_IntegralTagList where fk_scoreCriterion_id = 1 FOR XML PATH('')),1,1,''))

執行結果:

態度非常好,笑容甜美,效率很高,對人熱情,為他人着想,細心負責

 

接下來開始解決問題!!!

比如,查看表2中id=6的評價標簽,輸出結果為“態度非常好,笑容甜美”

      

解決方案如下:

(1)先把客戶評價表中的標簽序列對應的標簽查出來

(2)再將tagName進行拼接,變成下面這樣

 

開始實踐!!!

由於之前寫過這樣的查詢語句“select * from tabel where id in (1,2,3,4)”,所以想都沒想,直接將前端傳入的tagIDs = "1,2,3"直接查詢。

(-_-)|||  智障~居然犯這種低級錯誤~

繼續解決上面的問題,利用charindex,把id轉成字符,看是否包含於tagIDs里面

 (1)首先去tagIDs里id對應的標簽值

select a.tagName, b.id as appraisalId from tb_tagList a, tb_customerAppraisal b
where charindex(','+ltrim(a.id)+',',','+b.tagIDs+',')>0 

運行結果:

 (2)將相同appraisalId的標簽進行拼接,語句整理如下:

select b.id as appraisalId,a.tagName into #temp  from tb_tagList a, tb_customerAppraisal b 
where charindex(','+ltrim(a.id)+',',','+b.tagIDs+',')>0 

select appraisalId, tagNames = (stuff((select ',' + tagName from #temp where appraisalId =  c.appraisalId for xml path('')),1,1,'')) 
from #temp c group by c.appraisalId

drop table #temp 

執行結果:(這里將每一次評價的標簽都進行拼接,如有需要可以進行進一步地細節處理 )

 

 @_@)Y 分享到此結束~

 


免責聲明!

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



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