2016-07-11 4 views
0

VBAでSQL Group Byステートメントを実装しようとしています。私は4つの列(login_year、login_month、login_day、user_name)を持つシンプルなワークシートを持っており、毎月ログインした一意のユーザーの数を生成したい。VBAでSQL Group Byステートメントを実装する方法

ように、Oracle SQLは次のようになります。

SELECT 
login_year, 
login_month, 
COUNT(DISTINCT user_name) 
FROM users 
GROUP BY 
login_year, 
login_month; 

どのようにそれは、この使用してVBAを実装するのが最善でしょうか?

ご協力いただきありがとうございます。

+0

あなたは、ピボットテーブルを使用してみましたか? –

+0

これにアクセスする方法は不明ですが、カウントするにはcountという名前を付ける必要があります。count(Distinct user_name)as usercount –

+0

Excel 2010を使用していますが、Distinct Countオプションがあると思いますピボットテーブル。 – Mikeyjh

答えて

0

Dictionaryオブジェクトにアクセスするには、MS Scripting Libraryへの参照を設定する必要があります。

以下のコードは、年/月ごとに辞書エントリを作成します。各エントリには、名前の別の辞書が保持されます。子辞書のカウントは別個のカウントです。

Sub ListDistinctUserCount() 

    Dim vaValues As Variant 
    Dim dc As Scripting.Dictionary 
    Dim dcNames As Scripting.Dictionary 
    Dim i As Long 
    Dim sAllData As String 

    'read range into array 
    vaValues = Sheet1.Range("A2:D51").Value 
    Set dc = New Scripting.Dictionary 

    For i = LBound(vaValues, 1) To UBound(vaValues, 1) 
     'concat the year and month for dictionary key 
     sAllData = vaValues(i, 1) & "|" & vaValues(i, 2) 

     'if it's already added 
     If dc.Exists(sAllData) Then 
      'add the name if it doesn't exists 
      If Not dc.Item(sAllData).Exists(vaValues(i, 4)) Then 
       dc.Item(sAllData).Add vaValues(i, 4), vaValues(i, 4) 
      End If 
     Else 
      'otherwise add the year month and a new dict for the names 
      Set dcNames = New Scripting.Dictionary 
      dcNames.Add vaValues(i, 4), vaValues(i, 4) 
      dc.Add sAllData, dcNames 
     End If 
    Next i 

    For i = 0 To dc.Count - 1 
     Debug.Print dc.Keys(i), dc.Items(i).Count 
    Next i 

End Sub 

非常にエレガントではないが、私はより良い方法を考えることができませんでした。 VBA初心者のための

追加情報

A Variantデータ型は、他のデータ型を保持することができます。それは大きくて効率は低いが、場合によっては必要である。

マルチセル範囲のRange.Valueプロパティは、2次元の1ベースの配列を返します。その配列をバリアントに割り当てて、それをループすることができます。これは、個々のセルを読み取るよりもはるかに高速です。 Excelのグリッドへの読み書きは非常に遅いため、配列全体を読み込んでその方法でデータを操作するのが一般的です。

VBAには、データを格納するためのCollectionオブジェクトがあります。 Scripting.Dictionaryオブジェクトには、.Existsプロパティのような優れた機能があり、すべてのキーまたはアイテムを配列として書き出す機能がいくつかあります。スクリプトライブラリは既定でOfficeと共にインストールされますが、既定では新しいプロジェクトには含まれません。あなたはツールに行く必要があります - 参照トンそれを含める。

辞書は、他の多くの言語で見られるように、キーアイテムリストです。アイテムは、ほぼすべてのデータ型にすることができます。この場合、アイテムは別の辞書です。

+0

お返事ありがとうございました。これは面白いです、私はあなたのロジックを理解するためにいくつかのバックグラウンドの読書をする必要があります。 VBAの初心者はここ:)。 – Mikeyjh

0

Jet/ACE SQLエンジン(Access、Excelを含むMS Office/Windowsプログラムで使用)では、COUNT(DISTINCT ...)は他のRDMSと比較して維持されませんが、派生テーブルを使用して、外部クエリでそれらを数えます。

SQL(以下の文字列として埋め込ま)

SELECT u.login_year, u.login_month, COUNT(*) As usercount 
FROM 
    (SELECT user_name, login_year, login_month 
    FROM users 
    GROUP BY user_name, login_year, login_month) As u 
GROUP BY u.login_year, u.login_month; 

VBA(ADOドライバ/プロバイダ接続)

Sub RunSQL()  
    Dim conn As Object, rst As Object 
    Dim strConnection As String, strSQL As String 
    Dim i As Integer 

    Set conn = CreateObject("ADODB.Connection") 
    Set rst = CreateObject("ADODB.Recordset") 

    ' CONNECTION STRINGS (TWO VERSIONS) 
' strConnection = "DRIVER={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" _ 
'      & "DBQ=C:\Path\To\Workbook.xlsm;" 
    strConnection = "Provider=Microsoft.ACE.OLEDB.12.0;" _ 
         & "Data Source='C:\Path\To\Workbook.xlsm';" _ 
         & "Extended Properties=""Excel 8.0;HDR=YES;"";" 

    strSQL = " SELECT u.login_year, u.login_month, COUNT(*) As userCount " _ 
       & " FROM " _ 
       & " (SELECT user_name, login_year, login_month " _ 
       & " FROM users" _ 
       & " GROUP BY user_name, login_year, login_month) As u" _ 
       & " GROUP BY u.login_year, u.login_month;"      
    ' OPEN DB CONNECTION 
    conn.Open strConnection 
    rst.Open strSQL, conn 

    ' COLUMN HEADERS 
    For i = 1 To rst.Fields.Count 
     Worksheets("RESULTS").Cells(1, i) = rst.Fields(i - 1).Name 
    Next i   
    ' DATA ROWS 
    Worksheets("RESULTS").Range("A2").CopyFromRecordset rst 

    rst.Close: conn.Close  
    Set rst = Nothing: Set conn = Nothing  
End Sub 
+0

ありがとうパフェこれは私が探していたものです!あなたは私に背景を与えるために本やブログをお勧めできますか? – Mikeyjh

+0

Googleはあなたの友人です。 [ワークブックのクエリ](https://technet.microsoft.com/en-us/library/ee692882.aspx)に関するこのMicrosoftチュートリアルを参照してください。 – Parfait