- PR -

テーブルを選ぶSQLについて

1
投稿者投稿内容
会議室デビュー日: 2005/09/06
投稿数: 2
投稿日時: 2005-09-06 21:00
VB6、Accessで開発しています。

今、Accessのdbに以下のようなテーブルがあります。
mainテーブル、
ct_1テーブル、
ct_2テーブル、
ct_3テーブル

mainテーブルの項目は
No(主キー)、Date、Time、TableName です。
ct_番号のテーブル項目は
type(主キー)、Name、Item です。

上記のようにmainテーブルとct_番号テーブルで結合出来るキーはない状態です。

この状態で、
mainテーブル.TableName の項目に「ct_1テーブル」といった風にテーブル名が登録されています。

そのTabkeNameに登録されているCt_番号のテーブルのレコード件数を数えて、
以下の1〜4の情報を取得したいのですが、

1:mainテーブル.No
2:mainテーブル.Date
3:mainテーブル.Time
4:mainテーブル.TableNameに登録されているct_番号テーブルのレコード件数

(ct_番号テーブルはmain情報のデータが増えるにつれ、追加されます。)

この情報を一本(出来ない場合は複数)のSQLで取得することは可能なのでしょうか?
VBのソース上で工夫しないと無理なのでしょうか…。
そのSQLの書き方など、ご存知の方が居られましたらご教授お願い致します。
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2005-09-06 23:42
引用:

楓さんの書き込み (2005-09-06 21:00) より:
この情報を一本(出来ない場合は複数)のSQLで取得することは可能なのでしょうか?


一本のデータベースで取得することは不可能でしょう。もちろん"ct_xxx"テーブルの数だけSQL分を実行すれば、取得することは可能です。一番理想的なのは、テーブル構成を再設計する事かと・・・。

パフォーマンス上の理由から四半期毎とか、一年毎とかの単位でテーブルを作成し分離している例は皆無ではありませんが、お世辞にも良い設計ではないかと。まして、テーブルを分離する必要が発生するほど負荷の高いデータベースをACCESS MDBで作成するのはやめた方が良いんじゃないかなぁ・・・。

仮に、その場合でもmainテーブルとリンクするためのフィールドぐらいは用意しておくと良いです。そうすればUnion等でテーブルを結合することで、一回のSQL分でデータを取得することが可能になります。

_________________
甕星 <mikahosi@abox9.so-net.ne.jp>
http://blogs.msmvp.jp/mikahosi/
sophia(rc)
会議室デビュー日: 2005/09/02
投稿数: 18
投稿日時: 2005-09-07 09:26
あまりスマートではないですが、こんなのはいかがでしょうか?

SELECT m.No, m.Date, m.Time, c.cnt FROM mainテーブル m INNER JOIN
(SELECT 'ct_1テーブル' as TableName, count(*) as cnt from ct_1テーブル UNION select 'ct_2テーブル', count(*) from ct_2テーブル UNION select 'ct_3テーブル', count(*) from ct_3テーブル) as c
ON m.TableName=c.TableName;

サブクエリ部分を選択クエリとして別に作っておけばもう少し見やすくなると思います。
でっち6号
大ベテラン
会議室デビュー日: 2005/01/31
投稿数: 176
お住まい・勤務地: Kawasaki
投稿日時: 2005-09-07 10:16
AccessならIIFも使えますね。

コード:

SELECT Main.*,
IIF(tabname='ct_1', (SELECT COUNT(*) FROM ct_1),
IIF(tabname='ct_2', (SELECT COUNT(*) FROM ct_2),
IIF(tabname='ct_3', (SELECT COUNT(*) FROM ct_3),0))) AS CNT
FROM Main;



多分岐なら、CASEだろ!と思い、下も試したのですが、
「演算子がありません」とエラーになってしまいました。
便乗で申し訳ないのですが、どなたかおかしい点を指摘して
いただけないでしょうか。

コード:

SELECT Main.*,
CASE Main.tabname
WHEN 'ct_1' THEN (SELECT COUNT(*) FROM ct_1)
WHEN 'ct_2' THEN (SELECT COUNT(*) FROM ct_2)
WHEN 'ct_3' THEN (SELECT COUNT(*) FROM ct_3)
ELSE 0 END
AS CNT
FROM Main;



※ENDがなかったので追加

[ メッセージ編集済み 編集者: でっち6号 編集日時 2005-09-07 10:22 ]
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-09-07 10:28
検索クエリは件数が多いと死ねますよ... orz



_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
kanai
ベテラン
会議室デビュー日: 2004/09/13
投稿数: 98
投稿日時: 2005-09-07 13:21
静的なSQLでは、新しい「ct_番号」テーブルが増えるたびに定義を変更しなくては
ならなくなり、保守上の問題が発生します。
したがって、VB側で動的SQLを組んで対応することになるかと思います。

指定されたテーブル名の行数を返す関数を作成し、main.TableNameを引数として
渡すことにすれば比較的簡単かと思います。

Accessのモジュールに下記の関数を組み込んでおけばできるかな?と思い、実際に
やってみましたがだめでした。Accessのクエリとしては動作するものの、VBなどの
外部からの呼び出しはできないようです。

コード:
Public Function GetRowCount(ByVal tableName As String) As Integer
    Dim count As Integer
    Dim sql As String
    Dim rs As DAO.Recordset
    sql = "SELECT COUNT(*) FROM " & tableName
    Set rs = CurrentDb.OpenRecordset(sql)
    count = CInt(rs.Fields(0).Value)
    rs.Close
    Set rs = Nothing
    GetRowCount = count
End Function

(呼び出し側)
SELECT main.*,GetRowCount(main.TableName) FROM main



関係ありませんが、Oracleだったらストアドファンクション+動的SQLの
組み合わせで実現できます。
1

スキルアップ/キャリアアップ(JOB@IT)