質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Access

Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

3回答

630閲覧

縦持ちレコードでレコード追加時にSQL修正することなく可変横持化したい。

Otazoman

総合スコア44

Access

Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2018/03/14 10:12

前提・実現したいこと

縦持ちのテーブルを横展開するSQL文を書きましたが
今のままでも動作はするのですが
レコードが追加された際にいちいちSQLの修正が発生するので
これを避けたいと考えております。

該当のソースコード

SQL

1SELECT 2 m_search.code, 3 Max(IIf([m_search.panel_no]="1",[m_search.search_flg])) AS 1, 4 Max(IIf([m_search.panel_no]="2",[m_search.search_flg])) AS 2, 5 Max(IIf([m_search.panel_no]="3",[m_search.search_flg])) AS 3, 6 Max(IIf([m_search.panel_no]="4",[m_search.search_flg])) AS 4, 7 Max(IIf([m_search.panel_no]="5",[m_search.search_flg])) AS 5, 8 Max(IIf([m_search.panel_no]="6",[m_search.search_flg])) AS 6, 9 Max(IIf([m_search.panel_no]="7",[m_search.search_flg])) AS 7, 10 Max(IIf([m_search.panel_no]="8",[m_search.search_flg])) AS 8, 11 Max(IIf([m_search.panel_no]="9",[m_search.search_flg])) AS 9, 12 Max(IIf([m_search.panel_no]="10",[m_search.search_flg])) AS 10, 13 Max(IIf([m_search.panel_no]="11",[m_search.search_flg])) AS 11, 14 Max(IIf([m_search.panel_no]="12",[m_search.search_flg])) AS 12, 15 Max(IIf([m_search.panel_no]="13",[m_search.search_flg])) AS 13, 16 Max(IIf([m_search.panel_no]="14",[m_search.search_flg])) AS 14 17FROM m_search.panel_no 18GROUP BY m_search.code 19ORDER BY m_search.code;

試したこと

VBAとループを使ってSQLを動的に生成すれば実現できそうだとは思うのですが、
ゆくゆくSQlite等に移行することも考えているので、できればそれを踏まえて
SQL文のみで実現できないかと考えております。
色々とGoogleで調べてみたりしたのですがなかなかこれだという
情報に巡り合えませんでした。
どうしてもプログラムのみしか解決策がないのであれば仕方ないのですが
SQLのみで解決できる手段があれば知りたいです。
すいませんがお力をお貸しください。

補足情報(FW/ツールのバージョンなど)

MS-ACCESS2016
Windows10Pro 64bit
ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

SQLiteと共通のSQLで実現するというのは厳しいかと思います。
ですので、クロス集計にしろ、現在の形にしろ、メンテナンスフリーにするのは、動的にSQLを生成することで、良いのではないでしょうか。
どのみち、SQLを実行するところからは同じなんですし。

もう一つは、そのクロス集計の結果を必要としている機能を見直すという方法もありますね。

追記

以下の自作関数を作成するなら、SQLはメンテナンスフリーにできるかと思います。
DJoin 関数 - リスト文字列を取得する方法

尚、取り出しの際に配列として処理する必要もありですが。

投稿2018/03/14 16:07

編集2018/03/16 01:19
sazi

総合スコア25173

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Otazoman

2018/03/15 00:02

クロス集計部分については横展開しないとフラグの設定がうまく動作しない関係もあってどうしても横展開せざるをえない箇所です。 メンテナンスフリーとするとなるとフロント側でパラメータ長を取得して そのパラメータ長を元に動的にCASE文を必要数展開するというやり方が 簡単かもしれないですね。
guest

0

見た感じクロス集計クエリでよさそうです。
行見出しにcode
列見出しにpanel_no
値にsearch_flg

でいいかと思います。データに存在しない[panel_no]があると歯抜けになります。
歯抜けにしたくない場合強制的に表示させるためのオプションで「クエリ列見出し」があるので
そこを埋めると表示できるようになります。

#追記
あとでビット演算するとしたらこんなかんじですかね。flgが1か0だと楽なんですが…

sql

1SELECT 2 m_search.code, 3 sum(2^(clng([m_search.panel_no])-1)) AS panel_no_sum 4FROM m_search.panel_no 5WHERE m_search.search_flg=1 6GROUP BY m_search.code 7ORDER BY m_search.code;

投稿2018/03/14 12:42

編集2018/03/14 14:59
sousuke

総合スコア3828

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Otazoman

2018/03/14 13:00

早速のご回答ありがとうございます。 実はクロス集計クエリで生成したものをSQLに焼き直そうとしているところです。 そのクロス集計クエリに別のクエリをつなげていて、それをベースにSQLを 準備してそのSQLをVBA以外の別言語で使用する予定です。 それでSQLに置き換えた際に動的にレコード追加した際にメンテナンスレスな SQLの書き方がないかなぁと思って質問した次第です。 IIFとCASEを使った書き方だとメンテナンスが発生するのでそのメンテナンスを 回避したいと思っています。
sousuke

2018/03/14 13:24

ピボットはSQL Serverならわりかしいけるんですが、SQLiteになるとわからないですね…。 別のアプローチとしては考えられるのは データはフラグのようなので1列にすべてをふくめてビット演算する ということでしょうか。 フラグが立っているもの中で2のpanel_noでべき乗して2進数化することで そのsumをビット演算で取り出して使うというやり方です。 どうやって使っているのかわからないのであれなんですが… 1,0,1,1,0→13(2進数表記で10110) こんな感じなイメージです。 これで扱うとSQLは一通りで済んでフロントのプログラムだけごちゃごちゃ すればいいことになります。
Otazoman

2018/03/14 23:58

ご回答ありがとうございます。意図されているところ理解できました。 確かにpanel_no毎に含まれているsearch_flgの値を1行にして 出力するとすれば、SQLの変更はいらなくなりますね。 search_flgですがNullと1と2というのが現在のパラメータです。 そのため1010のようにきれいに並んでおらず意図する値が 取り出せないかもしれません。 ※実際に試すと値はうまく取れませんでした。 色々とありがとうございました。
sousuke

2018/03/15 00:07

そこはNULL、1、2を列にすればいいと思いますよ。 SELECT m_search.code, sum(iif([search_flg]=1,2,0)^(clng([m_search.panel_no])-1)) AS panel_no1_sum, sum(iif([search_flg]=2,2,0)^(clng([m_search.panel_no])-1)) AS panel_no2_sum, sum(iif(isnull([search_flg]),2,0)^(clng([m_search.panel_no])-1)) AS panel_noNULL_sum FROM m_search.panel_no GROUP BY m_search.code ORDER BY m_search.code; これで panel_no1_sumにflg=1 panel_no2_sumにflg=2 panel_noNULL_sumにflg is NULL のビット値がはいるのでそれぞれandで取り出せば一応取れます。 flgの数が増えるとSQLに変更が出ますが、flgの数が増えることは よっぽどだと思います。
Otazoman

2018/03/15 05:48

ありがとうございます。 早速試してみます。
guest

0

結局、以下の様な形でしのぎました。

JavaScript

1 var getPanel = 'SELECT m_search.panel_no ' 2 + 'FROM m_search ' 3 + 'GROUP BY m_search.panel_no ' 4 + 'ORDER BY m_search.panel_no;' 5 var panNoJson = getJsonData(getPanel); 6 //横展開の表を作成する 7 var sPivotSql = 'SELECT m_search.code, ' 8 var rt = JSON.parse(panNoJson); 9 for(var i=0;i < rt['data'].length;i++){ 10 var targetNo = rt['data'][i].panel_no; 11 // MS-ACCESS用 12 sPivotSql = sPivotSql + ' Max(IIf([m_search.panel_no]=' + targetNo 13 +',[m_search.search_flg])) AS' + targetNo + ',' ; 14 // SQLite用 15 sPivotSql = sPivotSql + ' Max(case when panel_no=' + targetNo 16 + 'then search_flg else 0 end ) AS \'' + targetNo + '\''; 17 if(i !== rt['data'].length - 1 ){ 18 sPivotSql = sPivotSql + ','; 19 } 20 } 21 sPivotSql = sPivotSql + ' FROM m_search ' 22 + 'GROUP BY m_search.code ' 23 + 'ORDER BY m_search.code;' 24 console.log(sPivotSql); 25

色々とヒントをいただき
ありがとうございました。

投稿2018/03/16 01:11

Otazoman

総合スコア44

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問