目錄
需求
范例運行環境
數據樣本設計
功能實現
上傳EXCEL文件到數據庫
SQL語句
小結
需求
在日常的應用中,排查列重復記錄是經常遇到的一個問題,但某些需求下,需要我們排查一組列之間是否有重復值的情況。比如我們有一組題庫數據,主要包括題目和選項字段(如單選選擇項或多選選擇項),一個合理的數據存儲應該保證這些選項列之間不應該出現重復項目數據,比如選項A不應該和選項B的值重復,選項B不應該和選項C的值重復,以此窮舉類推,以保證這些選項之間不會出現重復的值。本文將介紹如何利用group by 、having 語句來實現這一需求,主要實現如下功能:
(1)上傳 EXCEL 版試題題庫到 MS SQL SERVER 數據庫進行導入
(2)通過 union all 將各選項列的數據進行 轉記錄行的合并
(3)通過 group by 語句和 count 聚合函數統計重復情況
(4)通過 having 子句篩選出重復記錄
范例運行環境
操作系統: Windows Server 2019 DataCenter
數據庫:Microsoft SQL Server 2016
.netFramework 4.7.2
數據樣本設計
假設有 EXCEL 數據題庫如下:
如圖我們假設設計了錯誤的數據源,第4題的A選項與D選項重復,第8題的A選項與C選項重復了。
題庫表 [exams] 設計如下:
序號
字段名
類型
說明
備注
1
sortid
int
排序號
題號,唯一性
2
etype
nvarchar
試題類型
如多選、單選
3
etitle
nvarchar
題目
4
A
nvarchar
選項A
5
B
nvarchar
選項B
6
C
nvarchar
選項C
7
D
nvarchar
選項D
功能實現
上傳EXCEL文件到數據庫
導入功能請參閱我的文章《C#實現Excel合并單元格數據導入數據集》這里不再贅述。
SQL語句
首先通過 UNION ALL 將A到D的各列的值給組合成記錄集 a,代碼如下:
select A as item,sortid from exams union allselect B as item,sortid from exams union allselect C as item,sortid from exams union allselect D as item,sortid from exams
其次,通過 group by 對 sortid (題號) 和 item (選項) 字段進行分組統計,使用 count 聚合函數統計選項在 題號 中出現的個數,如下封裝:
select item,count(item) counts,sortid from (select A as item,sortid from exams union allselect B as item,sortid from exams union allselect C as item,sortid from exams union allselect D as item,sortid from exams
) a group by sortid,item order by sortid
最后使用 having 語句對結果集進行過濾,排查出問題記錄,如下語句:
select item,count(item) counts,sortid from (select A as item,sortid from exams union allselect B as item,sortid from exams union allselect C as item,sortid from exams union allselect D as item,sortid from exams
) a group by sortid,item having count(item)>1 order by sortid
在查詢分析器運行SQL語句,顯示如下圖:
由此可以看出,通過查詢可以排查出第4題和第8題出現選項重復問題。
小結
我們可以繼續完善對結果的分析,以標注問題序號是哪幾個選項之間重復,可通過如下語句實現:
select case when A=item then 'A' else ''end+
case when B=item then 'B' else '' end +
case when C=item then 'C' else '' end +
case when D=item then 'D' else '' end tip
,b.* from
(select item,count(item) counts,sortid from (select A as item,sortid from exams union allselect B as item,sortid from exams union allselect C as item,sortid from exams union allselect D as item,sortid from exams
) a group by sortid,item having count(item)>1 ) b,exams c where b.sortid=c.sortid
關鍵語句:case when A=item then ‘A’ else ''end+
case when B=item then ‘B’ else ‘’ end +
case when C=item then ‘C’ else ‘’ end +
case when D=item then ‘D’ else ‘’ end tip
這個用于對比每一個選項列,得到對應的選項列名,運行查詢分析器,結果顯示如下:
這樣我們可以更直觀的看到重復的選項列名是哪幾個,以更有效幫助我們改正問題。在實際的應用中每一個環節我們都難免會出現一些失誤,因此不斷的根據實際的發生情況總結經驗,通過計算來分析,將問題扼殺在搖籃里,以最大保證限度的保證項目運行效果的質量。
至此關于排查多列之間重復值的問題就介紹到這里,感謝您的閱讀,希望本文能夠對您有所幫助。