- - PR -
SQLで困ってます。
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2004-03-25 21:42
カレンダマスタ(CALMST)を参照して出庫マスタ(SMST)の出庫日[SYMD]、
到着日数[TSU]から到着日付を算出するSQLを教えてください。 CALMST(カレンダマスタ) CYMD ------ 4/2 4/3 4/4 4/5 4/6 4/7 SMST(出庫マスタ) NO |SYMD|TSU ----------- 001 |4/2 |2 002 |4/3 |1 003 |4/1 |5 この2つのマスタで このような結合した表を作成したいのです。 SMST(出庫マスタ) NO |SYMD|TSU|CYMD ------------------------------- 001 |4/2 |2 |4/4 (4/2の2日後は4/4) 002 |4/3 |1 |4/4 (4/3の1日後は4/4) 003 |4/2 |5 |4/7 (4/2の5日後は4/7) ここで1回のSQL1文でこの表をつくることは可能でしょうか? カレンダマスタ(CALMST)を参照して出庫マスタ(SMST)の出庫日[SYMD]、 到着日数[TSU]から到着日付を算出して出庫マスタに付与するSQLを 1回のSQLで求め方を教えてください。 CALMST(カレンダマスタ) CYMD ------ 4/2 4/3 4/4 4/5 4/6 4/7 SMST(出庫マスタ) NO |SYMD|TSU ----------- 001 |4/2 |2 002 |4/3 |1 003 |4/1 |5 この2つのマスタで 出庫日を起点とした到着日一覧表を作成したいのです。 出庫日[SYMD]と到着日数[TSU]は出庫マスタが持ってます。 NO |SYMD|TSU|CYMD ------------------------------- 001 |4/2 |2 |4/4 (4/2の2日後は4/4) 002 |4/3 |1 |4/4 (4/3の1日後は4/4) 003 |4/2 |5 |4/7 (4/2の5日後は4/7) こんな感じにしたいのですが・・・ TOP句などを利用したりして頑張ってみたのですが うまくできませんでした。 どなたかご教授してください。よろしくお願いします。 | ||||||||
|
投稿日時: 2004-03-25 21:46
すみません。投稿が同じ文書がまじってしまいました。
正しく掲載します。 カレンダマスタ(CALMST)を参照して出庫マスタ(SMST)の出庫日[SYMD]、 到着日数[TSU]から到着日付を算出するSQLを教えてください。 CALMST(カレンダマスタ) CYMD ------ 4/2 4/3 4/4 4/5 4/6 4/7 SMST(出庫マスタ) NO |SYMD|TSU ----------- 001 |4/2 |2 002 |4/3 |1 003 |4/1 |5 この2つのマスタで 出庫日を起点とした到着日一覧表を作成したいのです。 出庫日[SYMD]と到着日数[TSU]は出庫マスタが持ってます。 NO |SYMD|TSU|CYMD ------------------------------- 001 |4/2 |2 |4/4 (4/2の2日後は4/4) 002 |4/3 |1 |4/4 (4/3の1日後は4/4) 003 |4/2 |5 |4/7 (4/2の5日後は4/7) こんな感じにしたいのですが・・・ TOP句などを利用したりして頑張ってみたのですが うまくできませんでした。 どなたかご教授してください。よろしくお願いします。 | ||||||||
|
投稿日時: 2004-03-25 21:52
私はSQLSeverしか弄った事ありませんが、SQLServerならばDATEADDって関数があります。
それを使用すればカレンダマスタを見る必要すらないのですが……。 | ||||||||
|
投稿日時: 2004-03-25 21:56
DBMSが不明なので良く分かりませんが・・・
Oracleで、以下のようなテーブル定義なら、
とするだけじゃないですか? ※ テーブル定義が
と仮定・・・ ※ テーブル定義に関する記述を追記 [ メッセージ編集済み 編集者: Cluster 編集日時 2004-03-25 21:58 ] | ||||||||
|
投稿日時: 2004-03-25 22:33
はにまるです。
Oracleでヒントをお話します。 記述内容からすると、ある程度、経験がある様なので考え方のみ 勝手に補足追加。 まず、カレンダーマスタは「営業日」の日付のみを所有し、休日は含まない。 到着日数は、「営業日」のみで計算するとします。 1.出庫マスタを取る (1)select NO,SYMD,TSU from SMST 2.出庫日を起点(起算日)として営業日を取得する。 (1)select CYMD from CALMST where SYMD >= 起算日 日付で並べる。 (2)select CYMD from CALMST where SYMD >= 起算日 order by CYMD 到着日数分、カレンダーマスタを取得 (3)select CYMD from(2−(2)のselect文) where rownum <= 到着日数 最大値を取得 (4)select max(CYMD) as CYMD from(2−(3)のselect文) 3.1の考えと2の考えを外部結合で1つのSQLとする。 という感じで段階的に考えると行けます。 ただ、見た目で何をしているか解らないのでお奨めしません。 1.ファンクションを作る。 create function FNC_COMP_CYMD(起算日 in date,到着日数 in number) return CHAR 計算処理 end; 2.select文で1を利用し select FNC_COMP_CYMD(SYMD,TSU) from SMST; とした方が良いと思います。 こちらの方が、別処理で同じ内容を求められた時に楽ですし、 営業日換算で算出する考えは、ちらほら有りますので、 今後も活用出来ます。 | ||||||||
|
投稿日時: 2004-03-25 23:37
みなさんResありがとうございます。
落社員さん > 私はSQLSeverしか弄った事ありませんが、SQLServerならばDATEADDって関数があります。 >それを使用すればカレンダマスタを見る必要すらないのですが……。 すみません説明不足でした。 カレンダマスタは実働日のみが入っているマスタです。 なので参照しにいかねばならないのです。 > DBMSが不明なので良く分かりませんが・・・ すみませんSqlServer2000(sp2)です >select NO, SYMD, TSU, SYMD+TSU CYMD from SMST; カレンダマスタを参照しにいかねばならないのです。 説明が悪かったです。すみません。 はにまるさん >勝手に補足追加。 はにまるさんの補足説明の通りです。 >という感じで段階的に考えると行けます やはり副問い合わせを駆使して作らなければなりませんよね? 複雑でもかまいませんのでどのようなSQLになるのでしょうか? ちなみにOracleではなくSqlServerなんです。 そこで考えたのが select max(cymd) cymd from (select top 到着日数 cymd from CALMST where cymd > 起算日 order by cymd) で・・top句を利用して作ってみようと思ったのですが・・・・ 到着日数と起算日は出庫マスタのものですのでどう結合すれば いいかわからなくなり困った次第です。 (top句にファイルの項目なんかつかえなさそうですしね) やはりその後に記述のようにFNC_COMP_CYMDなどの Funcionを作成した方が分かりやすいのでしょうか? なんとか1回のSQLでしたいのです。 複雑でもかまいませんのでどのようなSQLになるかご教授お願いします。 | ||||||||
|
投稿日時: 2004-03-26 02:34
はにまるさんがOracleにおけるアプローチですでに説明されていますが
SQLServer2000でもFunctionを作成することが可能ですので、 Functionを作られてSQL分から使用されたほうがいいと思います。 (ターゲットにSQLServer7が含まれるのであれば無理ですが) SQLServerの場合exec関数を使ってSQLを動的に生成して実行することが 可能ですからそれを利用するとtopの後ろの行数も簡単に指定できるかと 思います。 また、日数が短ければFETCHで指定日数分回してやるということも、 可能です。 やり方はいろいろ考えられると思いますが... ただどうしても1SQL分で解決したいということであれば 制約はありますが、カレンダマスタにシーケンシャルな番号を 振ってやる列を用意してやれば実現できると思います。 例えば、 ID CYMD --- ---------- 1 2004/04/02 2 2004/04/03 3 2004/04/04 4 2004/04/05 5 2004/04/06 6 2004/04/07 として SELECT dbo.SMST.ID, dbo.SMST.SYMD, dbo.SMST.TSU, CALMST_1.CYMD FROM dbo.CALMST INNER JOIN dbo.SMST ON dbo.CALMST.CYMD = dbo.SMST.SYMD INNER JOIN dbo.CALMST CALMST_1 ON CALMST_1.ID = dbo.CALMST.ID + dbo.SMST.TSU で希望される結果になると思います。 ただこの場合、番号は飛び番なしで日付順のシーケンシャルでなければ ならないという制約がでてくるため、日付の挿入や削除があるたびに 番号の振りなおしが発生します。 ほかにも考えればよい方法があるかもしれません。 | ||||||||
|
投稿日時: 2004-03-26 08:42
Oracleでやるなら、テーブル上でシーケンシャルな番号は振らず、副問い合わせにして、ROWNUMを見るという手もあるかも・・・? 〜〜〜〜〜 副問い合わせの中に条件が書けないですね。ボツ 〜〜〜〜〜 いや、ビューを使うという方法がありました。CALMSTはそのままで、 CREATE OR REPLACE VIEW V_CALMST ( NUM, CYMD ) AS SELECT ROWNUM, CYMD FROM CALMST ORDER BY CYMD; べーちゃんさんの、CALMSTを見ているところを、V_CALMSTに変更する。 #実行時間が犠牲になります [ メッセージ編集済み 編集者: Jitta 編集日時 2004-03-26 09:20 ] |