
以前こちらで教えていただいのですが、
http://oshiete.goo.ne.jp/qa/8086569.html
以下のクエリを実行すると、「Nullの使い方が不正です」とのエラーが出てしまいます。
------------------------------------
テーブル名「T9」
フィールド:顧客番号(テキスト)/ 売上金額(通貨) / 売上月(テキスト
テーブル名「T9A」
フィールド:顧客番号(テキスト)/ 集約先番号(テキスト)
●標準モジュール
Public Function Bango(sSrc As String) As String
Dim rs As New ADODB.Recordset
Dim sR As String
sR = sSrc
rs.Source = "SELECT * FROM T9A WHERE 顧客番号='" & sSrc & "';"
rs.Open , CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
If (Not rs.EOF) Then sR = Bango(rs("集約先番号"))
rs.Close
Bango = sR
End Function
●クエリ
SELECT Bango(顧客番号) AS 集約番号, Sum(売上金額) AS 売上金額計, 売上月
FROM T9
GROUP BY Bango(顧客番号), 売上月;
------------------------------------
当初は、テーブル「T9A」には集約先番号を持つ顧客番号のみにするはずでしたが、
便宜上、集約先番号の有無にかかわらず、すべての顧客番号が入ったテーブルを使います。
そのため、「T9A」の集約先番号にはNullがあり、
Nullに対しては、同行の顧客番号を返すように対応したいです。
If IsNull(集約先番号) Then・・・とやるのかな?と浮かびましたが、うまくいかず、困っております。
何卒ご指南くださいますよう、お願いいたいます。
No.4ベストアンサー
- 回答日時:
Q1が少しおかしかったですね。
正しくは以下のようになります。
Q1:
SELECT A.顧客番号,←★これが無かった。
Nz(E.集約先番号,Nz(D.集約先番号,
Nz(C.集約先番号,Nz(B.集約先番号,
A.集約先番号)))) AS 実集約先
FROM (((T9A AS A LEFT JOIN T9A AS B
ON A.集約先番号=B.顧客番号) LEFT JOIN
T9A AS C ON B.集約先番号=C.顧客番号)
LEFT JOIN T9A AS D
ON C.集約先番号=D.顧客番号) LEFT JOIN
T9A AS E ON D.集約先番号=E.顧客番号
それでQ2はこちら
SELECT Nz(B.実集約先,A.顧客番号) AS 集約番号,
売上月,売上金額 FROM T9 AS A LEFT JOIN
Q1 AS B ON A.顧客番号=B.顧客番号←★これが正しい。
Q3はそのままです。
前のクエリだと集約先がない顧客だと上手くいきません。
早速のご回答、ありがとうございました。
試してみたところ、期待したとおりの結果が得られました。
今回はいずれも大変勉強になる回答をいただけたのですが、
最も処理時間の速かった回答者様の投稿をベストアンサーとして選ばせて いただいきました。
どうもありがとうございました。
No.3
- 回答日時:
最大5レベルのネストであれば、以下のようにします。
クエリ:Q1
SELECT Nz(E.集約先番号,Nz(D.集約先番号,
Nz(C.集約先番号,Nz(B.集約先番号,
A.集約先番号)))) AS 実集約先
FROM (((T9A AS A LEFT JOIN T9A AS B
ON A.集約先番号=B.顧客番号) LEFT JOIN
T9A AS C ON B.集約先番号=C.顧客番号)
LEFT JOIN T9A AS D
ON C.集約先番号=D.顧客番号) LEFT JOIN
T9A AS E ON D.集約先番号=E.顧客番号
目的の一つ前のクエリ:Q2
SELECT Nz(B.実集約先,A.顧客番号) AS 集約番号,
売上月,売上金額 FROM T9 AS A LEFT JOIN
Q1 AS B ON A.顧客番号=B.実集約先
目的のクエリ:Q3
SELECT A.集約番号,Sum(A.売上金額) AS 売上金額計,
A.売上月 FROM Q2 GROUP BY A.集約番号,A.売上月
前にも述べましたが、SQLで実現する方法を考えるべきで、
プログラムでやると、700倍以上効率が悪く、特にODBCの
リンクテーブルを使うと、コーヒー一杯飲んでくる時間が
あくほど性能が劣化します。
上記設計で、拙いのはネストが5レベルもあることで、
別のテーブルを置くなりして、1レベルに収まるよう
工夫すべきです。
この回答への補足
いただいたものをそのままコピペして試してみました。
Sqlだとサクサク動くんですね!
しかし、結果が、
Q1クエリの実集約先が、nullのままになってしまいました。
Q3でも集計は顧客番号の集計結果と同じでした。
顧客番号、集約先が文字列だからしょうか?
何度もお手数をおかけしますが、よかったら教えてください。
どうもありがとうございます。
テーブルや効率・・・、
ご指摘の通り工夫が足りませんよね、なんとか改善していきたいです。
動作確認がまだですので、また結果を報告したいと思います。
No.2
- 回答日時:
集約先のネストは何段階まででしょう?
仮に集約先のネストが1レベルしかないと
するならば、以下のクエリで集約先を特定
します。
クエリ:Q1
SELECT A.顧客番号
,Nz(B.集約先,A.集約先) AS 実集約先
FROM T9A AS A
LEFT JOIN T9A AS B
ON A.集約先=B.顧客番号
Nz関数は以下の働きがあります。
Nz(A,B) Aが非NULLならA,AがNULLならB
このクエリの集約先で集計します。
クエリ:Q2
SELECT Nz(B.集約番号,A.顧客番号) AS 集約番号
,SUM(A.売上金額) AS 売上金額計,A.売上月
FROM T9 AS A LEFT JOIN Q1 AS B
ON A.顧客番号=B.実集約先
GROUP BY Nz(B.集約番号,A.顧客番号),A.売上月
サブクエリを使うと、Q1は要らないのですが、
SQLに不慣れのようなので、分けて作る方が
安全でしょう。
こういうものはクエリだけで処理すべきで、
それができない時はテーブルの設計が
間違っています。
ご回答いただきありがとうございます。
情報が漏れており、失礼いたしました。
集約先は最大5段階まで入れ子になっています。
不勉強で申し訳ないのですが、
1段階以上の入れ子構造の場合でも
クエリで処理できるものなのでしょうか?
No.1
- 回答日時:
案1) rs("集約先番号") が Null でなければ、再度 Bango を呼び出す
> If (Not rs.EOF) Then sR = Bango(rs("集約先番号"))
↓
If (Not rs.EOF) Then
If (Not IsNull(rs("集約先番号"))) Then sR = Bango(rs("集約先番号"))
End If
案2) Recordset を得る時の条件に 集約先番号 Is Not Null を追加してみる
> rs.Source = "SELECT * FROM T9A WHERE 顧客番号='" & sSrc & "';"
↓
rs.Source = "SELECT * FROM T9A WHERE 集約先番号 Is Not Null AND 顧客番号='" & sSrc & "';"
案3) 全面的に書き方を変えてみる
Public Function Bango(sSrc As String) As String
Dim v As Variant
Dim sR As String
v = sSrc
While (Not IsNull(v))
sR = v
v = DLookup("集約先番号", "T9A", "顧客番号='" & v & "'")
Wend
Bango = sR
End Function
※ 各処理性能はわかりません
※ 未検証ですので不都合あれば修正してください
※※ テーブル「T9A」での循環には注意してください
ブログに記事として載せてましたので、興味あれば探してみてください。
・自分の管理するURLは記述できない規則です
・また、辿りつくまでのキーワード提示もできません
この回答への補足
案1~3まで試して、期待した結果が得られることを確認できました!
どうもありがとうございました。
回答者様のブログを参考に、
もっと勉強しようと思います。
お礼が遅れまして失礼いたしました。
早速のご回答をいただきありがとうございます。
成長せず、何度もお手数をかけてしまい申し訳ないです。
回答者様のブログもあわせて確認しました。
テーブル「T9A」の集約先番号が、Nullが大多数を占めるので、
いただいた案1、案2を、まず試してみたいと思います。
Accessソフトが自宅PCに無いため、
動作確認については明後日以降報告いたします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Access(アクセス) Access IF文でテーブルに存在しない場合の処理について 2 2022/10/10 18:09
- その他(Microsoft Office) マクロVBAについて 1 2022/09/06 18:12
- Access(アクセス) access,vbaでフォルダ内のファイルをテーブルにインポート、ファイル名もフィールドに追加したい 1 2022/08/31 11:11
- Visual Basic(VBA) ユーザーフォームの表示を追加したい 2 2023/03/26 23:18
- Visual Basic(VBA) 先ほど、回答者様によって教えていただいたのですがどうしたらいいか分かりません。 ユーザーフォーム上に 2 2023/02/21 22:25
- Visual Basic(VBA) InputBoxでキャンセルボタンを押したらファイル自体を閉じたい 3 2022/07/23 17:52
- Visual Basic(VBA) access count数を変数に格納 2 2022/03/30 19:21
- Excel(エクセル) Excel 指定した固有番号で、複数の行を削除する方法は? 2 2022/03/30 15:18
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたいの続き 5 2023/01/24 00:16
- Visual Basic(VBA) ユーザーフォーム「frm_基本❶」を立ち上げると新規で入力する行数を右下のNoとして表示しています。 1 2023/03/16 19:02
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセル ADO Filterでは一気...
-
同じ商品なのに、JANコード...
-
固定電話着信履歴 181 ・・・・...
-
至急お願いいたします! ゆう...
-
電話番号 +817673467911という...
-
電話をかけるのに、違う番号を...
-
モバイルsuicaを持っており、 ...
-
携帯番号変える時は、それなり...
-
BBセキュリティの再インストール
-
フリーダイヤルのけた数
-
if関数を使って割引率をだす
-
ACSESS初心者です マンション管...
-
823で始まる電話番号
-
ダイヤル式のポストが空かなく...
-
自分の確認番号がわからない
-
FAX番号の英語表記とは?
-
携帯の下4けたのアイデア募集です
-
学籍番号の下一桁
-
pcでGoogleアカウントを作ろう...
-
999で始まる電話番号から着信が...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
999で始まる電話番号から着信が...
-
電話をかけるのに、違う番号を...
-
至急お願いいたします! ゆう...
-
81・・・・・から始まる電話...
-
同じ商品なのに、JANコード...
-
固定電話着信履歴 181 ・・・・...
-
電話番号 +817673467911という...
-
フリーダイヤルのけた数
-
P/Nとは?
-
1から5までの番号が1つずつ書か...
-
MS Wordで図表番号を1から振り...
-
FAX番号の英語表記とは?
-
携帯番号変える時は、それなり...
-
謎の電話番号
-
すべて「ひとつ・・・」ではじ...
-
エクセル ADO Filterでは一気...
-
823で始まる電話番号
-
if関数を使って割引率をだす
-
銀行で番号札は?
-
不気味な番号
おすすめ情報