@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

SQLで困ってます。

投稿者投稿内容
よねちん
ベテラン
会議室デビュー日: 2002/09/18
投稿数: 55
投稿日時: 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句などを利用したりして頑張ってみたのですが
うまくできませんでした。

どなたかご教授してください。よろしくお願いします。

よねちん
ベテラン
会議室デビュー日: 2002/09/18
投稿数: 55
投稿日時: 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/02/12
投稿数: 14
投稿日時: 2004-03-25 21:52
私はSQLSeverしか弄った事ありませんが、SQLServerならばDATEADDって関数があります。
それを使用すればカレンダマスタを見る必要すらないのですが……。
Cluster
ぬし
会議室デビュー日: 2003/03/06
投稿数: 289
お住まい・勤務地: 大阪
投稿日時: 2004-03-25 21:56
DBMSが不明なので良く分かりませんが・・・

Oracleで、以下のようなテーブル定義なら、
コード:


select NO, SYMD, TSU, SYMD+TSU CYMD from SMST;


とするだけじゃないですか?

※ テーブル定義が
コード:

名前 型
------ -----------
NO VARCHAR2(3)
SYMD DATE
TSU NUMBER(1)


と仮定・・・

※ テーブル定義に関する記述を追記

[ メッセージ編集済み 編集者: Cluster 編集日時 2004-03-25 21:58 ]
はにまる
ぬし
会議室デビュー日: 2003/12/19
投稿数: 969
お住まい・勤務地: 誤字脱字の国
投稿日時: 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;

とした方が良いと思います。
こちらの方が、別処理で同じ内容を求められた時に楽ですし、
営業日換算で算出する考えは、ちらほら有りますので、
今後も活用出来ます。
よねちん
ベテラン
会議室デビュー日: 2002/09/18
投稿数: 55
投稿日時: 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になるかご教授お願いします。


べーちゃん
大ベテラン
会議室デビュー日: 2002/07/21
投稿数: 121
投稿日時: 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

で希望される結果になると思います。
ただこの場合、番号は飛び番なしで日付順のシーケンシャルでなければ
ならないという制約がでてくるため、日付の挿入や削除があるたびに
番号の振りなおしが発生します。
ほかにも考えればよい方法があるかもしれません。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-03-26 08:42
引用:

べーちゃんさんの書き込み (2004-03-26 02:34) より:

ただこの場合、番号は飛び番なしで日付順のシーケンシャルでなければ
ならないという制約がでてくるため、日付の挿入や削除があるたびに
番号の振りなおしが発生します。
ほかにも考えればよい方法があるかもしれません。


 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 ]

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