SQL文、JOINの記述を教えてください
LEFT JOIN ( SELECT 得意先CD,得意先名 FROM 得意先M ) TM
ON TM.得意先CD=MAIN.得意先CD
と記述するのと
LEFT JOIN 得意先M TM ON TM.得意先CD=MAIN.得意先CD
では実行速度は変わりますか?
後者の方が記述が少なくて済むので後者へ切り替えていこうと思いまして。
-
nkmtさん
始めまして。
DBが何か、質問には記述がありませんが、Oracle、SQLServer など、RDBMSとして考えてみます。
実行計画を見ないと何とも言えませんが、一般論としては、後者のほうが速いのではないかと予想できます。
得意先M の主キーのセグメントが「得意先CD」であれば特にそうです。
前者は、先に得意先マスターのレコードセットを取得してからの抽出となりますが、後者は得意先マスターの統計情報を利用して抽出できそうです。ですから、私だったら後者の書き方をします。
以上、ご参考になれば幸いです。
-
舩木様、お世話になります。DBはSQLServerです。
そうなんですね、後者の方が速いのかもしれないのですね。
ご回答ありがとうございました。
後者の記述に慣れたいと思います。
最近はMagic上でSQL文を多用しております。まだまだ素人です。
最近の悩み事は、主のSQLの日付項目2つを利用してGROUP BY SUM のSQL文をJOINするWHEREに、
主SQLの日付項目2つを利用して、BETWEENのWHERE絞りをしたいですけどわかりません。
-
nkmtさん
以下は私のやり方です。最適解ではないかもしれません。
集計関数の結果を取得したい場合には、SQLコマンドタブでSQLを直に記述します。
その結果がレコードセットで帰ってきます。これをMagicのメインテーブルと見立てて処理をするという流れです。
その時に、Betweenを日付項目で使用するときには、パラメータを文字列変換した日付項目したものを送り、SQL文中でCastを使って日付型に変換をしています。
例:SQLコマンドに以下のように書きます。
select a from hoge where a between cast(':1' as DATETIME) and cast(':2' as DATETIME)
2つのパラメータは日付をDSTR関数で日付変換したものです。ロケールを気にしないといけませんが、こんな感じです。
参考になれば幸いです。
-
舩木様 ありがとうございます。
Magicでメインソースの代わりにSQLコマンドを使い、入力パラメータを渡し、結果を取得する方法は会得しております。
わかりにくい投稿をしてしまい失礼しました。以下のような事を実現するSQL文を書きたいです。
担当者マスタから担当者コードと担当者名を全員表示しつつ
担当者マスタに登録された正社員登用日の半年後の売上も集計表示するといったSQL文です。
Aさん、2019/4/1社員登用、2019/10/1~の売上 100万円
Bさん、2018/7/1社員登用、2019/ 1/1~の売上 500万円
担当者名は担当者マスタから
売上は売上データから、但し、担当者マスタの情報を元に集計期間が担当によって異なる
といったSQL文を私は書けません。
-
nkmtさん
質問の意図を誤っていました。失礼いたしました。
SQL文を書いてみました。テストしてませんが。
select 担当者, 社員登用日, sum(売上金額) 売上金額
from (select M.担当者CD, M.担当者, M.社員登用日, D.売上金額
from 担当者マスタ M
join 売上データ D
on D.担当者CD = M.担当者CD and D.売上日 >=
DATEADD(
month
, 6, M.社員登用日)
)group by 担当者CD, 担当者, 社員登用日
こんな感じ?細かいところは調整必要です。(登用日は月の1日が入っているか?とか)
with句を使った方がパフォーマンスが出るかもです。
(今、バッチ処理中で待機中)
ご健闘を祈ります。
-
Withっていう記述があるのも初めて知りました。ありがとうございます。チャレンジしてみます。
-
nkmtさん、舟木さん、こんにちは。
私なりにクエリ文を考えてみました。
サブクエリ使って担当者ごとの売上金額を求めています。SELECT
M.担当者コード,
M.担当者名,
M.正社員登用日,
(
SELECT
SUM(D.金額)
FROM 売上データ D
WHERE
D.担当者コード = M.担当者コード AND
D.売上日付 >= DATEADD(month, 6, M.正社員登用日)
) AS 売上金額
FROM
担当者 M
; -
mukaidaさん ありがとうございました。
SQL文 1項目ずつ左揃えで並べるのもこれまたいいですね。
実はSQLの質問の仕方を間違えておりました。
担当者別、月別に予算データがある。
Aさんは4月~6月で月別に3件登録されている。
Bさんは、5月~12月で8件登録されている。
1名1行で、その目標設定されたMIN(年月)~MAX(年月)と同期間の売上伝票を集計する
といった感じでした。またチャレンジしたいと思います。
-
nkmtさん、こんにちは。
ちょっとくどい感じがしますが、こんな感じでしょうか?
SELECT
M.担当者コード,
M.担当者名,
M.正社員登用日,
(
SELECT
MIN(年月)
FROM
予算データ Y
WHERE
Y.担当者コード = M.担当者コード
) AS 年月MIN,
(
SELECT
MAX(年月)
FROM
予算データ Y
WHERE
Y.担当者コード = M.担当者コード
) AS 年月MAX,
(
SELECT
SUM(D.金額)
FROM 売上データ D
WHERE
D.担当者コード = M.担当者コード AND
D.売上日付 BETWEEN
(
SELECT
MIN(年月)
FROM
予算データ Y
WHERE
Y.担当者コード = D.担当者コード
) AND
(
SELECT
MAX(年月)
FROM
予算データ Y
WHERE
Y.担当者コード = D.担当者コード
)
) AS 売上金額
FROM
担当者 M
; -
MUKAIDA様、またまた有難うございます。
メインのSELECTの中に、()で囲ってSELECTを書けるとは知りませんでした。
何か別のデータをくっつけるのはJOINしか知りませんでした。
とても感謝しております。
Magicで標準的な作りをしていれば、他データベースへも乗り換えが可能
という利点がありますが、実際その必要に迫られた事が私はありませんし
親子バッチタスクで集計PGを作るのもいいんでしょうけど、工数面で考えても
私ならこちらを取ります。SQLを使えばメンテナンス性が・・・・という声も聞きますが、タスク構造が
シンプルになる分、使った方が良さそうな気がします。当初、担当者マスタの正社員登用日などを記載しましたが
説明の為に思いついた説明の為だけのダミー項目でした。こんな感じで完成です。
一言で言えば、予算設定と同期間の売上を集計して、予算対比するという事です。
SELECT 管理番号
,YD.担当者コード
,TM.担当者名
,MIN(年月)
,MAX(年月)
,SUM(予算額),(SELECT SUM(税抜計) FROM 売上伝票D UD
WHERE YD.担当者コード=UD.担当者コード
AND 日付 BETWEEN MIN(年月) AND MAX(年月)
) 売上実績FROM 予算D YD
JOIN 担当者M TM ON TM.担当者コード=YD.担当者コード
GROUP BY 管理番号,YD.担当者コード,TM.担当者名
※WHEREのMAX(年月)は実際には、LEFT(MAX(年月))+'99'にしております。
今回の場合、Magicの標準的な作りであれば、WFを用意して、
予算データをWFへ書き出しリンク。あるいはソートしつつ変数加算し、ブレイク時に
WFへ登録リンク。次の売上集計タスクで同様の集計処理を記述となれば
工数増となるわけで。メンテナンス性でいえばSQL文を共通理解するスキルが必要でしょうね。
舩木様、Mukaida様 お付き合い頂きありがとうございました。
知人のMagic使いにも説いていければと思います。
でもなかなか拒絶反応もおきてしまいます。
サインインしてコメントを残してください。
コメント
10件のコメント