中年システムエンジニアのオモチャ箱

中年システムエンジニアが初体験のブログ活動。技術情報の備忘録以外も、色々と載せていければと思います。


VB.NET DataTable で Distinct(重複行の除外)する方法


【スポンサーリンク】


システム開発で欠かせないのが、データベースですよね。

そして、VB.NET では、DataTable クラスを使用して操作する方法が多いと思います。

また、DataTable クラスはデータベース以外でも使えるので、覚えておくと便利ですよ!

 

ちなみに、データベースの接続/操作方法については、中年 SE の下記ブログを読んでみてくださいね。

www.ma-se.com

DataTable オブジェクトに列を追加/データを追加

まずは、下記ソースを参考に DataTable オブジェクトに列とデータを追加してみましょう!

尚、フォームには DataGridView コントロール(GrdNormal と GrdDistintc)を 2 つ追加してあります。

用途は、DataTable オブジェクトにセットした値を表示するためです。

 

ソースコード 1(a)

'変数の宣言
Dim dt As New DataTable()
Dim row As DataRow = Nothing

 

'DataTable に列を作成
dt.Columns.Add("EMP_CD", Type.GetType("System.String"))
dt.Columns.Add("EMP_NAME", Type.GetType("System.String"))
dt.Columns.Add("FLOOR", Type.GetType("System.Int32"))
dt.Columns.Add("MEMO", Type.GetType("System.String"))

 

'DataTable の列と同じレコードを生成、及び、値の設定


'1 レコード目
row = dt.NewRow()
row("EMP_CD") = "001"
row("EMP_NAME") = "経理部"
row("FLOOR") = 1
row("MEMO") = String.Empty
dt.Rows.Add(row)

 

'2 レコード目
row = dt.NewRow()
row("EMP_CD") = "002"
row("EMP_NAME") = "営業部"
row("FLOOR") = 1
row("MEMO") = String.Empty
dt.Rows.Add(row)

 

'3 レコード目
row = dt.NewRow()
row("EMP_CD") = "003"
row("EMP_NAME") = "開発部"
row("FLOOR") = 1
row("MEMO") = String.Empty
dt.Rows.Add(row)

 

'DataGridView に DataTable の値を表示
GrdNormal.DataSource = Nothing
GrdNormal.DataSource = dt

上記プログラムを実行すると、GrdNormal グリッドビューには下記の通り表示されます。

f:id:middle-aged-se:20180814193712j:plain

一番下の行(*が表示されている行)は、新規追加行となるので、今回追加したレコードではありませんので注意してくださいね。

 

上記ソースの続きで、下記ソースを追加してください。

内容は、「FLOOR」列と「MEMO」列の値を Distinct し、重複行を除去したレコードを DataGridView に表示します。

 

ソースコード 2

'変数の宣言
Dim dv As DataView = Nothing
Dim dtDis As DataTable = Nothing

 

'作成した DatatTable に対する DataView を生成
dv = New DataView(dt)

 

'「FLOOR、MEMO」で Distinct したレコードを取得
dtDis = dv.ToTable(True, "FLOOR", "MEMO")

 

'DataGridView に「FLOOR、MEMO」で Distinct した値を表示
GrdDistintc.DataSource = Nothing
GrdDistintc.DataSource = dtDis

上記プログラムを実行すると、GrdDistintc グリッドビューには下記の通り表示されます。

f:id:middle-aged-se:20180814193709j:plain

3 レコードとも、

  • 「FLOOR」列には『1』
  • 「MEMO」列には『空文字』

がセットされているので、Distinct した結果は 1 レコードに纏まります

 

 
DataView の Distinct 動作の注意点【超重要】

中年 SE は昔、この DataView で Distinct した時に、どーしても想定した値が取得できなくてハマったことがあったので、注意点として記載しておきますね!

注意してほしい点は、Distinct する列に『NULL』値が含まれる列があるかどうかです。

ソースコード 1(a)を、下記のように修正して実行してみましょう。

ちなみに変更した内容は「2 レコード目の MEMO 列に、NULL 値(DBNull.Value)をセット」です。

 

ソースコード 1(b)

'変数の宣言
Dim dt As New DataTable()
Dim row As DataRow = Nothing

 

'DataTable に列を作成
dt.Columns.Add("EMP_CD", Type.GetType("System.String"))
dt.Columns.Add("EMP_NAME", Type.GetType("System.String"))
dt.Columns.Add("FLOOR", Type.GetType("System.Int32"))
dt.Columns.Add("MEMO", Type.GetType("System.String"))

 

'DataTable の列と同じレコードを生成、及び、値の設定


'1 レコード目
row = dt.NewRow()
row("EMP_CD") = "001"
row("EMP_NAME") = "経理部"
row("FLOOR") = 1
row("MEMO") = String.Empty
dt.Rows.Add(row)

 

'2 レコード目
row = dt.NewRow()
row("EMP_CD") = "002"
row("EMP_NAME") = "営業部"
row("FLOOR") = 1
row("MEMO") = DBNull.Value
dt.Rows.Add(row)

 

'3 レコード目
row = dt.NewRow()
row("EMP_CD") = "003"
row("EMP_NAME") = "開発部"
row("FLOOR") = 1
row("MEMO") = String.Empty
dt.Rows.Add(row)

 

'DataGridView に DataTable の値を表示
GrdNormal.DataSource = Nothing
GrdNormal.DataSource = dt

上記プログラムを実行すると、GrdNormal グリッドビューには下記の通り表示されます。

f:id:middle-aged-se:20180814193712j:plain

ソースコード 1(a)で実行した時と同じ表示結果ですよね。

でも、実際の値としては「NULL がセットされているので空文字とは違う」ということに注意してください。

 

ソースコード 2 は変更せずに実行してください。

すると、GrdDistintc グリッドビューには下記の通り表示されます。

f:id:middle-aged-se:20180814193707j:plain

1,3 レコード目には、

  • 「FLOOR」列には『1』
  • 「MEMO」列には『空文字』

をセットしました。

2 レコード目には、

  • 「FLOOR」列には『1』
  • 「MEMO」列には『DBNull.Value

をセットしました。

空文字と NULL は DataGridView に表示した際、セルには何も表示されないので、一見すると全く同じに見えます

しかし、実際の値としては空文字と NULL は別物なので、Distinct した結果は 2 レコードに纏まります

 

この動作に注意しないで、DataGridView だけを見て判断していると、調査しているときにハマる場合があるので気を付けてくださいね!

今回に限らず、データベースのデータを取り扱う際には、「NULLと空文字の違い」をしっかりと理解していきましょう!

中年 SE との約束だよ!!


Visual Basicの絵本 Windowsプログラミングわかる9つの扉


SQLの絵本 第2版 データベースが好きになる新しい9つの扉