iT邦幫忙

1

玩玩SQL~在資料表中計算相同字元有幾個? (6/30更新)

sql
  • 分享至 

  • xImage

隨便你用哪個SQL@@~我是使用MSSQL

我先放基本資料~你們試試看~

declare @Tmp table(
	StrTmp nvarchar(10)
)

insert into @Tmp
values(Nchar(55357) + Nchar(56374) + N'A' + Nchar(55357) + Nchar(56374))
,(N'ʕ•ﻌ•ʔ')
,(Nchar(55357) + Nchar(56893) +Nchar(55357) + Nchar(56893) +Nchar(55357) + Nchar(56893) +N'ʔʔʔ')
,(Nchar(55357) + Nchar(56374) + N'ʔʔʔ' + Nchar(55357) + Nchar(56374))
,(N'ﻌﻌﻌ')

結果如圖下~

https://ithelp.ithome.com.tw/upload/images/20210629/20061369MFzDrQlPaV.png

補充~沒想到IT邦~不支援貼特殊符號....= =||
先幫特殊符號編碼~


這部分我是用T-SQL來辦@@~看大家有無更好的方式~明天按解答結束~

declare @TmpAns table(
	StrTmp nvarchar(10)
	,UnicodeNum int
)

declare @i int=0,@Count int=0,@Str nvarchar(50)=''
select @Count=Count(0)
from @Tmp

declare @j int=0,@SubCount int=0

while(@i<@Count)
begin
	set @i = @i + 1

	select @Str=StrTmp
	from (
		select Row_Number()Over(order by StrTmp) Sort
		,StrTmp
		from @Tmp
	) k
	where Sort = @i

	set @j = 0
	set @SubCount = len(@Str)
	while(@j<@SubCount)
	begin
		set @j = @j + 1
		if(UNICODE(SUBSTRING(@Str,@j,1))=55357)
		begin
			insert into @TmpAns
			values(SUBSTRING(@Str,@j,2),UNICODE(SUBSTRING(@Str,@j,1)) + UNICODE(SUBSTRING(@Str,@j + 1,1)))
			set @j = @j + 1
		end
		else
		begin
			insert into @TmpAns
			values(SUBSTRING(@Str,@j,1),UNICODE(SUBSTRING(@Str,@j,1)))
		end
	end

end

select StrTmp
,Count(0) Num
from @TmpAns
group by StrTmp
,UnicodeNum
order by StrTmp

再次改良一次~這個就是用SQL去查詢了@@"

select StrShow
,Count(0) Num
from (
	select StrTmp
	,(
		case when UNICODE(SUBSTRING(StrTmp,Sort,1)) = 55357
		then SUBSTRING(StrTmp,Sort,2)
		else case when UNICODE(SUBSTRING(StrTmp,Sort,1)) not between 55357 and 60000 then SUBSTRING(StrTmp,Sort,1) else '' end
		end
	) StrShow
	,(
		case when UNICODE(SUBSTRING(StrTmp,Sort,1)) = 55357
		then UNICODE(SUBSTRING(StrTmp,Sort,1)) + UNICODE(SUBSTRING(StrTmp,Sort + 1,1))
		else case when UNICODE(SUBSTRING(StrTmp,Sort,1)) not between 55357 and 60000 then UNICODE(SUBSTRING(StrTmp,Sort,1)) else 0 end
		end
	) StrNum
	from @Tmp
	,(
		select Row_Number()Over(order by [number]) as Sort
		from master..spt_values
	) as k
	where Sort <= len(StrTmp)
) k
where len(StrShow) > 0
group by StrShow
,StrNum
order by StrShow


6/30更新

根據rogeryao提供字元補充字符定序後
Latin1_General_100_CI_AS_SC

這次查詢就沒有字元長度問題了~

select StrShow
,count(0) Num
from (
	select SUBSTRING(StrTmp collate Latin1_General_100_CI_AS_SC,Sort,1)StrShow
	from @Tmp
	,(
		select Row_Number()Over(order by [number]) as Sort
		from master..spt_values
	) as k
	where Sort <= len(StrTmp collate Latin1_General_100_CI_AS_SC)
) k
group by StrShow
order by StrShow desc

使用定序總類參考:
https://docs.microsoft.com/zh-tw/sql/relational-databases/collations/collation-and-unicode-support?view=sql-server-ver15

是否說是 計算字元 而不是 計算字串 ?
哈~不知道打哪個主題說明~才對~
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

4
一級屠豬士
iT邦大師 1 級 ‧ 2021-06-29 15:46:18
最佳解答

https://ithelp.ithome.com.tw/upload/images/20210629/20050647Sj2AZSKa2P.png

https://ithelp.ithome.com.tw/upload/images/20210629/20050647dFInC0ksiJ.png

https://ithelp.ithome.com.tw/upload/images/20210629/20050647lZ81UJ3pYP.png

這postgreSQL查詢真好用@@!

雖然沒有照我的題庫設定@@~
但postgreSQL應該判斷特殊符號當作只有一個字元~
因為MSSQL好像有特殊符號~判斷雙位數字元的問題~

例如以下~

select Nchar(55357) + Nchar(56893)
select Nchar(65228)

1
rogeryao
iT邦超人 8 級 ‧ 2021-06-29 16:26:27
CREATE TABLE Tmp (
StrTmp nvarchar(10));

INSERT INTO Tmp
values(Nchar(55357) + Nchar(56374) + N'A' + Nchar(55357) + Nchar(56374)),
(N'ʕ•ﻌ•ʔ'),
(Nchar(55357) + Nchar(56893) +Nchar(55357) + Nchar(56893) +Nchar(55357) + Nchar(56893) +N'ʔʔʔ'),
(Nchar(55357) + Nchar(56374) + N'ʔʔʔ' + Nchar(55357) + Nchar(56374)),
(N'ﻌﻌﻌ');
-- collate Latin1_General_100_CI_AS_SC : 計算長度時一個符號與一個字元一樣等於一
WITH CTE_X1 AS (
SELECT StrTmp,
SUBSTRING(StrTmp collate Latin1_General_100_CI_AS_SC,1,1) AS StrNew,
1 AS NUM
FROM Tmp
UNION ALL
SELECT StrTmp,
SUBSTRING(StrTmp collate Latin1_General_100_CI_AS_SC,NUM + 1,1) AS StrNew,
NUM + 1 AS NUM
FROM CTE_X1
WHERE LEN(StrTmp collate Latin1_General_100_CI_AS_SC) - NUM>0
)

SELECT StrNew,COUNT(1) AS 'Counter'
FROM CTE_X1 AS A
GROUP BY StrNew
ORDER BY StrNew DESC

Demo

看更多先前的回應...收起先前的回應...

哈~這招厲害~

不過這個Nchar(55357)是我硬查詢的@@"(因為IT邦不支援顯示)
如果有其他特殊符號就SQL查詢還要變更了~

rogeryao iT邦超人 8 級 ‧ 2021-06-29 16:52:17 檢舉

嗯,寫得不好,等高手出招。

我又加上~改良版的SQL了~這次就沒用到T-SQL了@@"

rogeryao iT邦超人 8 級 ‧ 2021-06-29 21:59:15 檢舉

/images/emoticon/emoticon12.gif

rogeryao iT邦超人 8 級 ‧ 2021-06-29 22:44:56 檢舉

To : 純真的人
我更新一版在上面了

我有在修正SQL了~因為字元判斷~
有雙位數字元的特殊符號組成@@
我抓一個區段判斷~後位數的字元是落在雙位數字元組合裡面~
就設定為空值

好唷~那我先把第一個解答~給第一位~
他的SQL看起來沒有雙字元位數的問題~

rogeryao iT邦超人 8 級 ‧ 2021-06-30 13:57:13 檢舉

To : 純真的人
再更新一版在上面了,
使用 collate Latin1_General_100_CI_AS_SC :
計算長度時一個符號與一個字元一樣等於一。

所以不須再用 UNICODE(SUBSTRING(StrTmp,1,1)) = 55357 了【與 55357 無關】,
SUBSTRING() 及 LEN() 皆能正確計算。

原來是要指定資料定序~才不會有字元不一樣的問題~
你厲害~找得出辦法~^.^

這次用了 Latin1_General_100_CI_AS_SC 字元定序~
查詢就簡單多了~~

我要發表回答

立即登入回答