dポイントプレゼントキャンペーン実施中!

お世話になります。
表題の通り、ACCESSクエリで連番を付けるにはどうすれば宜しいでしょうか?
調べたのですが、よく分からない為、
関数又は、SQLに詳しい方、よろしくお願いいたします。
(下記もDCOUNT関数でできますか?)

テーブル名:T_A
---------------------------
番号   名前   ランキング
1     佐藤    1
2     鈴木    2
3     佐藤    1
4     鈴木    2
5     佐藤    2
---------------------------
上記のテーブルがあったとして、特産品及び、ランキングを昇順すると、
下記の通りとなります。
---------------------------
番号   名前   ランキング
3     佐藤    1
1     佐藤    1
5     佐藤    2
4     鈴木    2
2     鈴木    2
---------------------------
ここで、連番という項目を追加して、上から1,2,3と連番を付けるにはどうすれば
宜しいでしょうか。
↓↓↓↓↓↓↓
(得たい結果)
------------------------------.
番号   名前   ランキング 連番←追加項目
3     佐藤    1       1
1     佐藤    1       2
5     佐藤    2       3
4     鈴木    2       4
2     鈴木    2       5
------------------------------
分かる方、教えてください。
よろしくお願い致します。

A 回答 (4件)

------------------------------.


番号   名前   ランキング 連番←追加項目
3     佐藤    1       1
1     佐藤    1       2
5     佐藤    2       3
4     鈴木    2       4
2     鈴木    2       5
------------------------------

要は、当該のId(=番号)が何番目に出現しているのか?
3--->1番目
1--->2番目

ならば、次のようなクエリを作成すれば目的は達成できます。

SELECT
  T1.ID,
  T1.名前,
  T1.ランキング,
  IdFound("SELECT ID FROM T1 ORDER BY [ランキング], 名前",[ID]) AS 連番
FROM T1
ORDER BY T1.名前, T1.ランキング;

さて、問題は IdFound() が提供されていないこと。
そこで、自作します。

Public Function IdFound(ByVal strSQL As String, ByVal Id As Integer) As Integer
  Dim N As Integer
  Dim M As Integer
  Dim rst As ADODB.Recordset
  
  Set rst = New ADODB.Recordset
  With rst
     .Open strSQL, _
        CurrentProject.Connection, _
        adOpenStatic, _
        adLockReadOnly
     If Not .BOF Then
       M = .RecordCount
       .MoveFirst
       For N = 1 To M
         If .Fields(0).Value = Id Then
           Exit For
         End If
        .MoveNext
       Next N
     End If
   End With
   IdFound = N
End Function

祈、成功!
「クエリで複数項目を昇順後、連番を付ける方」の回答画像1
    • good
    • 1

「番号」に重複がない長整数である事を前提にすると


一番簡単なのは、
テーブル「T_A」にフィールド「連番」(長整数)を設けて
VBA で「連番」を設定する事だと思います。


Public Sub Samp1()
  Dim rs As DAO.Recordset
  Dim sSql As String
  
  sSql = "SELECT 連番 FROM T_A ORDER BY 名前, ランキング, 番号 DESC;"
  Set rs = CurrentDb.OpenRecordset(sSql)
  While (Not rs.EOF)
    rs.Edit
    rs(0) = rs.AbsolutePosition + 1
    rs.Update
    rs.MoveNext
  Wend
  rs.Close
  Set rs = Nothing
End Sub


※ 上記 DAO の AbsolutePosition は、0 スタートの連番になるので
これを利用して単純に設定するものです。
(ADO に書き換える場合は、1 スタートなので + 1 は不要になります)
注意するのは、どの順番で得ておくか、だけです。
( ORDER BY 名前, ランキング, 番号 DESC )

フィールド「連番」を設けずにクエリだけで・・・とした場合、
1レコード毎に OpenRecordset すると、それだけでも遅くなると思うので
この「番号」の「連番」は何・・・
1度求めたものを Dictionary に格納しておいて、その中の情報を返す様にしてみます。


Dim dic As Object

Public Function myNoInit() As Boolean
  Dim rs As DAO.Recordset
  Dim sSql As String

  If (dic Is Nothing) Then
    Set dic = CreateObject("Scripting.Dictionary")
  End If
  dic.RemoveAll

  sSql = "SELECT 番号 FROM T_A ORDER BY 名前, ランキング, 番号 DESC;"
  Set rs = CurrentDb.OpenRecordset(sSql)
  While (Not rs.EOF)
    dic(rs(0).Value) = rs.AbsolutePosition + 1
    rs.MoveNext
  Wend
  rs.Close
  Set rs = Nothing
  myNoInit = True
End Function

Public Function myNo(vNum As Variant) As Long
  If (IsNull(vNum)) Then Exit Function
  If (dic Is Nothing) Then Call myNoInit
  myNo = dic(vNum)
End Function


上記を標準モジュールに記述しておいて、クエリでは以下のように

SELECT 番号, 名前, ランキング, myNo(番号) AS 連番
FROM T_A
WHERE myNoInit()
ORDER BY 名前, ランキング, 番号 DESC;


※ 不都合あれば修正してください。
    • good
    • 0

お詫びと訂正:



× IdFound("SELECT ID FROM T1 ORDER BY [ランキング], 名前",[ID])
〇 IdFound("SELECT ID FROM T1 ORDER BY 名前, [ランキング],",[ID])

当然に、[ID]が出現する位置を確認する為の SQL文とクエリの並び(ORDER BY XXX, XXX)は同じでなければなりません。先の回答では、それが一致していませんでした。当然に、名前→ランキングの順で並べないと正しく連番は付与されません。ちょっと、単純なミスがありましたので訂正しておきます。

PS、IdFound()→InRecord()

なお、関数名ですが Instr()に近い働きですので InRecord()と命名すべきだったかも知れません。
    • good
    • 0

  rst.Close


  Set rst = Nothing
End Function

最後は、推奨スタイルに直してください。
    • good
    • 1

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A