SQL質疑応答スレ 6問目 at DB
[2ch|▼Menu]
1:NAME IS NULL
08/05/16 21:21:17
参考リンク
URLリンク(sql.main.jp)
URLリンク(www.atmarkit.co.jp)
URLリンク(oraclesqlpuzzle.hp.infoseek.co.jp)
URLリンク(www.techscore.com)

前スレ:SQL質疑応答スレ 5問目
スレリンク(db板)

質問テンプレ
・DBとバージョン
・テーブルデータ
・欲しい結果
・説明

2:NAME IS NULL
08/05/16 21:22:37
過去ログ

SQL質疑応答スレ スレリンク(db板)
SQL質疑応答スレ Part 2 スレリンク(db板)
【帰ってきた】SQL質疑応答スレ スレリンク(db板)
【帰ってきた】SQL質疑応答スレ 2問目 スレリンク(db板)
【帰ってきた】SQL質疑応答スレ 3問目 スレリンク(db板)
【帰ってきた】SQL質疑応答スレ 4問目 スレリンク(db板)
SQL質疑応答スレ 5問目 スレリンク(db板)

3:NAME IS NULL
08/05/16 21:23:43
よくある質問

(問)
ID | DATE     | DATA
--+----------+-----
1 | 2007-11-11 | aaa
2 | 2007-11-11 | bbb
1 | 2007-11-10 | ccc
3 | 2007-11-12 | ddd
3 | 2007-11-11 | eee
4 | 2007-11-10 | fff
1 | 2007-11-12 | ggg

このようなテーブルから、下記のように

1 | 2007-11-12 | ggg
3 | 2007-11-12 | ddd
2 | 2007-11-11 | bbb
4 | 2007-11-10 | fff

各idに対して最新の1件だけ抽出するSQLの書き方を教えてください。

(答)
select A.ID,
    A.DATE,
    A.DATA
from TableName A
   inner join
   (select ID, max(DATE) as MAX_DATE
    from TableName
    group by ID
   ) B
   on A.ID = B.ID
   and A.DATE = B.MAX_DATE
;

4:NAME IS NULL
08/05/16 21:24:48
よくある質問

(問)
key   data
----------------
1     a
1     a
1     b
1     b
1     a
2     b
2     a
2     a

というテーブルから

key   a   b
--------------------
1    3   2
2    2   1

というExcelのピボットの様なデータを取得したいのですが、どういうSQLになりますか?
a,bというのは固定なので、仮にcというデータがあっても無視して構いません。

(答)
SELECT key,
    SUM(CASE data WHEN 'a' THEN 1 END) AS a,
    SUM(CASE data WHEN 'b' THEN 1 END) AS b
FROM table
GROUP BY key
ORDER BY key
;

5:NAME IS NULL
08/05/18 10:58:59 6+oG6BiD
インデックスの勉強がしたいのですが、
どういった方法がいいでしょうか?
たとえばインデックスの効果が体感できる
勉強方法とか教えてください。


6:NAME IS NULL
08/05/18 13:20:40
今時のPC性能だと趣味で勉強するレベルのデータ量では体感は不可能だと思うが。

7:NAME IS NULL
08/05/18 13:38:41
INDEXが有ることでSELECTが遅くなる
と紹介されることが多いけど、自分でも体験してみたいです。

8:NAME IS NULL
08/05/18 13:53:04
INDEXが有ることでSELECTが遅くなるなんてどこで紹介されてるんだ?

それはともかく、手っ取り早くテストデータ作るなら
PostgresとかMySQLについてるベンチマークでいいんじゃね?

9:NAME IS NULL
08/05/18 17:29:02
間抜けなインデックスが足を引っ張る、なんてのはあるけどね。
最近のおりこうさんなオプティマイザだと、そうそうないんじゃないかな

10:NAME IS NULL
08/05/18 17:45:53
前スレからのつづきで
auto_increment振ってみたらやっぱ順番バラバラで
auto_incrementフィールドの連番を振りなおしたい

やりたいことは
今あるテーブルのあるフィールドを昇順として
auto_incrementフィールドに1から連番をつけたいです。
お願いします(>_<)

11:NAME IS NULL
08/05/18 17:47:22
>>10
たぶん、DB によるんだろうけど、一般的な解としては
同じ構造のテーブルに入れ直す、ってとこじゃない?

12:10
08/05/18 17:52:52
別のテーブルを作るってこと?
名前は変えたくないんでできれば、今のテーブルを更新したいです。

色々調べてみてUPDATEとかRowNumでできそうな気がしたけど、わからんかったorz

13:NAME IS NULL
08/05/18 17:54:36
別のテーブルに入れた後、元のテーブルを削除して、
新しいテーブルを元の名前にすればOK

テンポラリテーブルを使ってもいいし。

14:10
08/05/18 18:09:27
ごめん。別のテーブルに入れるとこがわからん

CREATE TEMPORARY TABLE TmpTable SELECT * FROM SrcTable ORDER BY timestamp;
DROP TABLE SrcTable;
CREATE TABLE SrcTable AS SELECT * FROM TmpTable;
SrcTable:元テーブル
timestamp:並び替えに使うフィールド
これだとauto_incrementフィールドまでまんまコピーされてしまうし。

15:NAME IS NULL
08/05/18 18:23:41
auto_incrementをやめればいい

16:10
08/05/18 18:29:59
そっか。ちょっと調べてみまふ
ありがとう

17:NAME IS NULL
08/05/18 21:32:48 toQ3X+jn
こんなSQL作りたいのですが、お力を下さい。

社員表
社員番号 社員名 入社日
001      A 19950401
002   B 19960401
003      C 19950401

講座表
講座ID  講座名  開講日
aaaa   会計   20080501
bbbb   会計   20080601
cccc   エクセル 20080701

受講表
講座ID   社員番号
aaaa    001
aaaa    002
aaaa 003

ある講座名に該当する講座を取っている社員を全員列挙かつ入社年で絞込み、
または、誰も取っていなければ空行を出力したいです。

例えば講座名を「会計」、入社日を「19950401」で絞り込む場合、

講座ID 講座名 社員番号 社員名
aaaa  会計  001    A
aaaa  会計  003    C
bbbb  会計  (空)    (空)

と出力したいです。

あるいは「エクセル」と「19960401」で絞り混むと
講座ID 講座名  社員番号 社員名
cccc  エクセル (空)    (空)

これを自動化するため、1回のSQLで済ませたいのですが、
どのように書いたら良いでしょうか。

取ってる社員がいる場合といない場合とで、別々なSQLなら
簡単なのですが、1回となると難しくて困っています。


18:NAME IS NULL
08/05/18 22:06:26
>>17
UNION

19:NAME IS NULL
08/05/18 22:29:45 toQ3X+jn
ありがとうございます。

UNIONって、前半と後半で、
selectするデータの項目数があってないとダメですよね。

後半、社員番号と社員名にあたる列が空になるような
SQLはどう書いたら良いでしょうか・・・?

(csvに吐いて処理するので、カラム数が合って欲しいです)

20:NAME IS NULL
08/05/18 22:38:17
あー、ごめんごめん。

講座表と受講表を LEFT JOIN して、その結果と社員表を
INNER JOIN すれば OK だね

21:NAME IS NULL
08/05/18 23:18:37 toQ3X+jn
>その結果と社員表を INNER JOIN すれば OK だね

ありがとうございました。
副問い合わせ使いますよね?

何が難しいって、2つの表の結合なら、
外部結合すれば勝手に空のカラムが出るけど、

この場合みたいに、
中間的な表を介して3つの表で外部結合させる時の
空カラムの出し方が分かりませんでした。

22:NAME IS NULL
08/05/18 23:52:20
> 外部結合すれば勝手に空のカラムが出るけど、

join の left, right, inner, outer の意味わかってる?

23:NAME IS NULL
08/05/19 00:10:17 LUgEweM8
えーと

>講座表と受講表を LEFT JOIN して、
>その結果と社員表を INNER JOIN すれば OK だね

これの、1行目の結果が

講座ID 講座名 社員番号
aaaa   会計   001
aaaa   会計   003
bbbb   会計   (空)

ってな感じまでは分かりました。

select 講座ID、講座名、社員番号 from
講座表 LEFT JOIN 受講表
ON 講座表.講座ID = 受講表.講座ID

という感じ。

2行目が分かっていません…

24:NAME IS NULL
08/05/19 00:43:52
適当に書いてみた。
あってるかは知らん。

SELECT
 J.講座ID,
 K.講座名,
 J.社員番号
 S.社員名
 FROM
  講座表 K LEFT JOIN
  受講表 J ON K.講座ID = J.講座ID
  LEFT JOIN 
 (
 SELECT
   S.社員番号,
   S.社員名,
  FROM
   社員表 S
  WHERE
   S.入社日 = :入社日
 )S
 ON J.社員番号 = S.社員番号
 WHERE
 K.講座名 = :講座名

25:NAME IS NULL
08/05/19 10:31:56
受講表と社員表を先にINNER JOINしないとダメだね。

select 講座ID, 講座名, 社員番号, 社員名
from (select *
    from 講座表
    where 講座名 = '会計'
   )
   left outer join
   (select *
    from 受講表
       inner join
       社員表
       using (社員番号)
    where 入社日 = '19950401'
   )
   using (講座ID)
;

26:NAME IS NULL
08/05/19 15:27:36
すみません質問です
現在SQLServer2000とVisualStudioC#を使用して開発を行っています
サーバーが1台、クライアントが複数台で、各クライアントからは以下の処理を実行しています


1. テーブルから、ロックされていない未処理のデータを1件抽出
SELECT TOP 1 * FROM テーブル WHERE 処理フラグ=0 AND ロック=''

2. 取得した1レコードのキーを元にupdateを実行
UPDATE テーブル SET ロック='クライアントID' WHERE 処理フラグ=0 AND ロック='' AND キー='SELECTで取得したキー'

3. UPDATEの処理件数が1件であれば成功とし、SELECTで取得したキーを元にゆっくり編集作業を行う

4. 編集処理完了後、ロックフィールドを空にし、処理フラグを立てて更新する


上記の処理を繰り返すことにより、全レコードを重複なく編集することが目的だったのですが、
極まれに同じレコードを編集してしまうことがあるで困っています。手元の環境では再発しないので検証ができないもので…

上記の処理に何かまずい所があるのでしょうか?

27:NAME IS NULL
08/05/19 15:42:17
>>26
2の時点で一旦COMMITすれば起きないんじゃない?

ただ、3〜4が失敗した場合に2がロールバックされないという
新たな問題が発生することになるけど。

28:NAME IS NULL
08/05/19 16:19:45
返信ありがとうございます

書き忘れましたが、トランザクション処理は特に指定していません
なので、UPDATE処理終了後は自動的にCOMMITされている…という解釈でいいんですよね?
明示的にトランザクションで挟んだほうがいいんでしょうか?

ちなみに分離レベルはデフォルトのREAD COMMITEDです

29:NAME IS NULL
08/05/19 23:35:05
表のとある項目から、後ろから3桁目の数字が0である項目を抜き出したいのですがどうすればよいのでしょうか?
likeを使ったりしてるのですがわかりません。

30:NAME IS NULL
08/05/19 23:46:13
>>28
URLリンク(msdn.microsoft.com)

READPAST
他のトランザクションによってロックされている行を、データベース エンジンが読み取らないことを指定します。
多くの場合、この指定はページにも適用されます。
データベース エンジンは、ロックが解除されるまで現在のトランザクションをブロックする代わりに、
行やページをスキップします。
READPAST は、READ COMMITTED 分離レベルまたは REPEATABLE READ 分離レベルで実行中の
トランザクションでのみ指定できます。
SNAPSHOT 分離レベルで実行中のトランザクションにおいてこのオプションを指定する場合、
UPDLOCK や HOLDLOCK など、ロックが必要な他のテーブル ヒントと組み合わせて指定する必要があります。
READPAST を指定すると、行レベルとページ レベルの両方のロックがスキップされます。
READPAST は、UPDATE ステートメントまたは DELETE ステートメントで参照されるテーブル、
および FROM 句で参照されるテーブルで指定できます。UPDATE ステートメントで READPAST を指定した場合、
ステートメント内での指定場所にかかわらず、更新対象データ特定のためのデータ読み取り時にだけ適用されます。
INSERT ステートメントの INTO 句では、テーブルに READPAST を指定することができません。

READPAST を使用する読み取り操作はブロックを行いません。
READPAST を使用する更新操作や削除操作は、外部キーやインデックス付きビューの読み取り時、またはセカンダリ
インデックスの変更時にブロックを行う場合があります。

たとえば、テーブル T1 に整数型の列が 1 つあり、値 1、2、3、4、5 が格納されているとします。
このテーブルに対してトランザクション A で値 3 を 8 に変更し、この変更をまだコミットしていない間に
SELECT * FROM T1 (READPAST) を実行すると、取得される値は 1、2、4、5 となります。
READPAST は主に、SQL Server テーブルを使用する作業キューの実装時に、ロックの競合を減らすために使用します。
READPAST を使用するキュー リーダーは、他のトランザクションによってロックされたキュー エントリを、
ロックが解除されるまで待たずにスキップして、次に使用可能なキュー エントリへ進みます。


31:NAME IS NULL
08/05/19 23:54:02
>>29
ヒント:
SELECT
 SUBSTRING(RIGHT(T.COL1,3),1,1)
  FROM TABLE T

SQLServerならこれで右から3桁目がわかる。
varcharだけどね。

32:NAME IS NULL
08/05/20 00:03:13
>>29
WHERE ある項目 LIKE '%0__'
ある項目が数値型なら文字列型にキャストする

33:NAME IS NULL
08/05/20 13:08:54
>>31-32
ありがとうございます。
しかしうちはoracleな上、likeは使わずにやってみろと言われ頭がパンクしそうです(´・ω・`)
文字列の変換がヒントだと言われたのですが……アウアウ

34:NAME IS NULL
08/05/20 13:28:57
>>33
WHERE SUBSTR(ある項目, -3, 1) = '0'

35:NAME IS NULL
08/05/20 22:46:19
AさんとBさんの表がありまして
それぞれ葉抜けな日付のレコードに
AKとBKで1=出勤日 0=休日 NULL=未入力
で登録されたデータがあります

こいつから
A
ADATE AK
-------------------
2008/05/01 1
2008/05/03 1
2008/05/04 0
2008/05/05 1
2008/05/06 NULL

B
BDATE BK
-------------------
2008/05/02 1
2008/05/04 0
2008/05/06 0
2008/05/08 1
2008/05/08 NULL

↑こんな感じでA/BDATEにKEYがあります。
指定日(文字列で与えます)から誰かが出勤している5日分のリストを
ORACL10gのSQL1発で出力したくSQLを書いてみました
(登録されていない日はそれぞれ出勤日扱い)
が、20日先の限定になってしまいましたので
限定をつけない方法を教えてください

指定日=2008/05/03 の場合の抽出結果
-------------------
2008/05/03
2008/05/05
2008/05/06
2008/05/07
2008/05/08
となるようにしたいのです。

取りあえず頭に浮かんだSQL
select SDATE from (
select SDATE
from( (select to_date(指定日,'yyymmdd')+0 as SDATE from dual)
union(select to_date(指定日,'yyymmdd')+1 as SDATE from dual)
union(select to_date(指定日,'yyymmdd')+2 as SDATE from dual)
--省略--
union(select to_date(指定日,'yyymmdd')+20 as SDATE from dual)
)CL
left outer join A on A.ADATE=CL.SDATE
left outer join B on B.BDATE=CL.SDATE
where NVL(A.AK,1)=1 or NVL(B.BK,1)=1
order SDATE
) rownm<=5

よろしくお願いします。

36:35
08/05/20 22:51:18
ごめんなさい書きもれました
AK、BK=NULLも出勤日扱いです

37:NAME IS NULL
08/05/20 23:19:23
2008/05/07 も結果に入れたいってところに無理があるような。
ありえる日付を全て列挙した別テーブルを用意するのが常道じゃね?

38:NAME IS NULL
08/05/20 23:20:41
検証はしてない。
っていうかこのテーブルの作りはないだろ・・・。

SELECT
TOP(5)
FROM
(
SELECT
 A.ADATE AS TDATE
FROM A A
WHERE A.AK = 1
 OR A.AK IS NULL

UNION

SELECT
 B.BDATE AS TDATE
FROM B B
WHERE B.BK = 1
 OR B.BK IS NULL
)T
T.TDATE < :指定日
ORDER BY
TDATE DESC

39:NAME IS NULL
08/05/20 23:21:27
5/7もいれるのか!


40:NAME IS NULL
08/05/20 23:46:47
>>29
> 表のとある項目から、後ろから3桁目の数字が0である項目を抜き出したい

そもそもその項目の型はなんなのよ?

文字列型なら >>31>>33 でいいと思う。

>>33 に「文字列の変換がヒント」とか書いてるとこみると数値型かな?

だとすると後から3桁目って要するに百の位を言ってるのか?

1桁や2桁しかない時 (要するに 99 以下) の時はどうするんだ?

要するにやりたいことをちゃんと書け。

>>35
select top 5 SDATE from (
 select ADATE as SDATE from A
 where to_date(指定日,'yyymmdd') <= ADATE and NVL(AK, 1) = 1
 union
 select BDATE as SDATE from B
 where to_date(指定日,'yyymmdd') <= BDATE and NVL(BK, 1) = 1
)
order by SDATE

Oralce には top がないかもしれないが、そこは自分で何とかするように。

# と言うか、A さんと B さんで別々の表になってるというその設計を見直した
# ほうがいいと思うが。
# せめて、フィールド名ぐらいはあわせるとか...。

41:>>40
08/05/20 23:50:49
>>37, >>39
> 2008/05/07 も結果に入れたいってところに無理があるような。

ほんとだ、見落としてたよ。

>>37 の言う通り、日付マスタ用意するかストアドで動的に生成する
ぐらいしか思いつかない。

42:35
08/05/21 00:26:42
皆さんレスありがとうございます。
そうなんです。
2008/05/07 も結果に入れたい仕様なんです^^;
未来方向に確実に入力するのかは客次第で致し方ないとして

私の、数少ない経験でも
歯抜けな複数のカレンダーって何事?
もーテーブル設計のミスとしか思えないのですが
客が既設に拘りテーブルの統合や新設(特にマスター系)を極端に嫌うので...
#マスターが増えれば自分の仕事が増えるからいやだと嫌がったので
#自動でマスターを更新しますって言っても聞きいれてもらえなかった

43:NAME IS NULL
08/05/21 21:07:07
やはり馬鹿がコンピュータを使うとろくな事がないな w

44:NAME IS NULL
08/05/21 21:29:11 nC22OcKa
とある企業サイトでこんな文がでてきました
これはSQLインジェクションとかセキュリティの脆弱性につながりますか?

ORA-24374: define not done before fetch or execute and fetch
select seq,title,to_char(reg_date,'YYYY.MM.DD'),read_cnt,contents,vc_text from tb_corp_news where seq =

45:NAME IS NULL
08/05/21 22:21:20
>>42
歯抜けがせいぜいn日、とか、AとBを組み合わせると歯抜けがなくなる、
ならどうにかなるのでは

46:NAME IS NULL
08/05/21 23:20:35
バカがコンピュータでやってくる

47:35
08/05/21 23:49:16
>>45 様ありがとうです。

レコードがまったくなくても
出勤扱いで指定日から5日は必要なのですトホホ...

やっぱSQL1発はむりですかね?

#取りあえず30日の未来方向をMAXとすることで
#了解を取り付けたのですが...
#客がやっぱ不味いよーっていいそうなので
#VB側で処理を組んでおくつもり^^;



48:NAME IS NULL
08/05/22 00:21:18
手入力の無い日は自動入力するような仕組みを入れたほうがいい。

49:NAME IS NULL
08/05/22 00:34:43
>>47
勝手な予想だが、再帰使えば何とかなるような気がする。

気のせいかもしれないけど。

50:NAME IS NULL
08/05/22 00:35:14
>>49
親フィールドってなによ?

51:NAME IS NULL
08/05/22 20:06:24
UNIONなどは使用せずに以下のような
結果を1回の問い合わせで取得することは可能でしょうか?

テーブルのデータ
Col1 Col2 Col3
------------ ------------- --------------
AAA 100 200

取得結果
Col1 ColA
------------ -------------
AAA 100
AAA 200




52:NAME IS NULL
08/05/22 21:21:48
検証なし。

SELECT
T.COL1,
CASE WHEN
ROWCOL%2 = 0 THEN T.Col2
ELSE
T.Col3
END ColA
(
SELECT
A.Col1,
A.Col2,
A.Col3
FROM TABLE A,
TABLE B
)T

53:NAME IS NULL
08/05/22 21:25:31
ROWCOLってなんだ・・・・
ROW_NUMBER() OVER(ORDER BY Col1)
の間違い。


54:NAME IS NULL
08/05/22 21:45:43
「UNION などは使用」しない理由を書いた方がいいんじゃないか。

55:NAME IS NULL
08/05/22 21:50:35
>>54
UNIONを使用したくない理由は
実際は該当のレコードを取得するのに
相当コストの高いSQLになってしまうので
検索を複数回実行させたくないからです。

ちなみにDBはSQL Serverです。

>>52さんのSQLで実験中です。

できなそうですかね?

56:NAME IS NULL
08/05/22 22:13:35 I7jcq5Mc
すみません、教えてください><

アクセスを使っている初心者です。
以下の表から、「結果」のような表示をするにはどうしたらいいでしょうか?
やりたいことは、
商品コード2に値がある場合、商品コード2 から商品名を呼び出して表示、
商品コード2に値がない場合、商品コード2 とその商品名を 空 で表示
したいのです。

今日一日探したのですが、方法がわかりませんでした。
外部結合とか、やってみたのですが、わかりません。

どうかお願いします。
(見にくくてすみません)

受注表

受注番号_:_顧客コード_:_商品コード1_:_商品コード2_:
---------------------------------------------------
10001____:___001______:___102______:___103_______:
10002____:___002______:___101______:_____________:
10003____:___003______:___101______:___102_______:


顧客表

顧客コード_:_顧客名
---------------------
001________:_KUROKIYA
002________:_ONSIDE
003________:_FIRST HOUSE


商品表

商品コード_:_商品名 :
---------------------
101________:_BEER___:
102________:_JUICE__:
103________:_TEA____:


結果

受注番号:顧客コード:顧客名:商品コード1:商品名:商品コード2:商品名:
-------------------------------------------------------------------------
10001___:___001____:_KUROKIYA_____:___102____:_JUICE__:___103______:_TEA__:
10002___:___002____:_ONSIDE________:___101____:_BEER___:____________:______:
10003___:___003____:_FIRST HOUSE:___101____:_BEER___:___102______:_JUICE:

57:NAME IS NULL
08/05/22 22:18:52
>>55
>>52はテーブルデータが2行のときしかうまくいかないんじゃないのか?
ちなみに俺はUNIONしか思いつかんけど。

>>56
「外部結合」のキーワードまで辿り着いてるのに何でできないんだ?

58:NAME IS NULL
08/05/22 22:34:41
>>56
外部結合をやってみた、その内容を書いてみてもらえますか?

59:NAME IS NULL
08/05/22 22:35:31
Jet って Left Outer Join ってできたっけ?

60:NAME IS NULL
08/05/22 22:38:51
Jetかどうかで左右されるレベルじゃなくね?

61:56
08/05/22 22:47:53
早速のレスありがとうございます!!!!

JOIN操作の構文エラーになります。↓
(そもそも違う部分が間違っているかもしれませんが…)

SELECT
受注表.受注番号,
受注表.顧客コード,
顧客表.顧客名,
受注表.商品コード1,
商品表.商品名,
受注表.商品コード2,
商品表.商品名
FROM
((受注表
LEFT JOIN 商品表
ON 受注表.顧客コード=顧客表.顧客コード)
LEFT JOIN 商品表
ON 受注表.商品コード1=商品表.商品コード)
LEFT JOIN 商品表
ON 受注表.商品コード2=商品表.商品コード

62:NAME IS NULL
08/05/22 22:58:11
お、>>52の改変でできたかも。(>>51のやつね。)
ただしテーブルデータが1行しかないときは無理。

select Col1,
    case RN when 1 then Col2 else Col3 end as ColA
from (select A.*,
       row_number() over (partition by A.Col1 order by A.Col2) as RN
   from "TableName" A, "TableName" B
   )
where RN <= 2
;

しかしまあCROSS JOINよりは素直にUNIONしたほうが速いだろうねえ。。。

63:56
08/05/22 23:00:36
まちがえました!

FROM の中、

((受注表
LEFT JOIN 顧客表
ON 受注表.顧客コード = 顧客表.顧客コード)

商品表ではなく、顧客表です。

しかし、商品コード2が空白のため、
えらーになってしまいます。



64:NAME IS NULL
08/05/22 23:05:52
>>63
商品表は2つ別々にJOINしないといけないからエイリアスがいる

select ...
受注表.商品コード1,
A.商品名,
受注表.商品コード2,
B.商品名
from 受注表
left join 顧客表 on ...
left join 商品表 A on 商品コード1 = A.商品コード
left join 商品表 B on 商品コード2 = B.商品コード

65:NAME IS NULL
08/05/22 23:21:20
>>55
UNIONのコストが高くなるのが嫌ならUNION ALLをつかいなさい。

66:NAME IS NULL
08/05/22 23:24:52
>>62のやつ、後ろのTableName Bを2行のダミーテーブルにすれば
意外と使えるかもしれんと、今ふと思った。

67:NAME IS NULL
08/05/22 23:30:40
SELECT
T.Col1,
T.ColA
FROM
(
SELECT
Col1,
Col2 AS ColA,
'1'
FROM
TABLE

UNION ALL
Col1,
Col3 AS ColA,
'2'
FROM
TABLE
)T

68:NAME IS NULL
08/05/22 23:34:38
>>55
> 相当コストの高いSQLになってしまうので

ちゃんと測定した?

って言う前に、そんなこと心配するならテーブル構造
見直した方がいいんじゃないかと...。

69:56
08/05/22 23:46:58
>>64
ありがとうございます!
何度もすみません、レスを拝見して、
SELECT ...
受注表.商品コード1, A.商品名,
受注表.商品コード2, B.商品名
FROM ((受注表
LEFT JOIN 顧客表...)
LEFT JOIN 商品表 A ON 商品コード1 = A.商品コード)
LEFT JOIN 商品表 B ON 商品コード2 = B.商品コード

と、書きましたが、うまくいきません。

「商品コード1 = A.商品コード」のところにフォーカスがあたって、
エラーになります。間違っているのはどこでしょう??(;_;)



70:NAME IS NULL
08/05/23 01:13:11
検証なし。
SELECT
受注表.商品コード1, A.商品名,
受注表.商品コード2, B.商品名
FROM ((受注表 J
LEFT JOIN 顧客表 K ON J.顧客コード = K.顧客コード)
LEFT JOIN 商品表 A ON K.商品コード1 = A.商品コード)
LEFT JOIN 商品表 B ON K.商品コード2 = B.商品コード


71:56
08/05/23 01:49:54
>>70
できました!!!!
これで眠れます(;_;)
本当にありがとうございました!!!!


SELECT
受注表.受注番号,
受注表.顧客コード,
顧客表.顧客名,
受注表.商品コード1, A.商品名,
受注表.商品コード2, B.商品名
FROM ((受注表 受注表
LEFT JOIN 顧客表 顧客表 ON 受注表.顧客コード=顧客表.顧客コード)
LEFT JOIN 商品表 A ON 受注表.商品コード1=A.商品コード)
LEFT JOIN 商品表 B ON 受注表.商品コード2=B.商品コード;

72:NAME IS NULL
08/05/23 04:21:22 psBkKcpD
ID,親のID,コンテンツ
というような構造でフォルダのような階層を表現しているとき、
あるIDを与えて、そこから上の階層のIDを一気に取得する方法ってありますか?
ファイルのパスを取得するような形です。

73:NAME IS NULL
08/05/23 04:33:28
>>72
「SQL CONNECT BY」あたりでググる。

74:NAME IS NULL
08/05/23 04:52:24 psBkKcpD
>>73
ありがとう。

75:55
08/05/23 17:15:09
結局>>67みたいなSQLで処理することにしました。

>>68さん
実行プランで測定しましたよ。
実行時間も抽出に2分くらいかかります。

テーブル定義は既存システムの改修なので手が出せません。

みなさん、いろいろありがとうございました。

76:NAME IS NULL
08/05/23 17:33:13
ORACLE10g(10.1.0.2.0)使ってます

こんなのあるとしまつ。
SELECT TRUNC(num * rate, 0) FROM DUAL;

変数内を見ると
num=3600000
rate=0.37777777777・・・・

返ってくる値は、1360000
なぜにと思い、つらつらやっていると


SELECT TRUNC(3600000 * 0.37777777777777777777777777777777777777, 0) FROM DUAL;
----------
1359999

SELECT TRUNC(3600000 * 0.377777777777777777777777777777777777777, 0) FROM DUAL;
----------
1360000

これって何でですの?


77:NAME IS NULL
08/05/23 17:40:50
単なる浮動小数点演算の誤差だろJK

78:76
08/05/23 18:39:36
>>77
あれだと、Numberで38桁、、、誤差だろJK
で話終わっちゃうよなぁ確かに。

79:NAME IS NULL
08/05/23 21:27:07
Oracleだからという話ではないな。

80:NAME IS NULL
08/05/23 23:26:36
IEEE754でぐぐると何か分かるかも

81:NAME IS NULL
08/05/24 02:00:03
そんなアメリカの規格、知りませんのだ(><)

82:76
08/05/24 02:09:41
>>80
オイラ宛てでしたか。退社直後でした。すみません。
調べておくですわ。

データ30万件強のうち数件程度ありやがったが
ダメな場合の法則性みたいのが分かんね。


83:NAME IS NULL
08/05/24 02:23:58
有効桁数というか、精度というか。
ま、テストデータ作ればすぐ分かるよ。

84:76
08/05/24 04:25:51
>>83
というか、ナンバー型とフロート型を掛けたらナンバー型に暗黙変換かかって
切り捨て部分が四捨五入になった
でいいっすか。

これで月曜の報告はのりきろうかと。
ついでに電卓片手に1円違うというのは勘弁してと言うわ。


85:NAME IS NULL
08/05/24 13:42:17
>>84
銀行は1円合わないと銀行内を怒号が飛び交うというのに。
金がらみのシステムやるなら1円の差を馬鹿にしてはいけないよ。

86:NAME IS NULL
08/05/24 13:44:41
つーか完全に仕様不備ですな

87:NAME IS NULL
08/05/24 14:58:51
Oracle的には仕様で、使う側が勘違いしている典型的な例だな。

88:NAME IS NULL
08/05/24 15:23:06
>>74
勘定系ならその言い訳した時点で全てが終わる。
素直にあやまっとけ。

89:NAME IS NULL
08/05/24 15:33:58
勘定系やってるヤツでこんなバカいたらマッハでクビになると思うが。

90:NAME IS NULL
08/05/24 16:44:59
IEEE754じゃなくて十進化浮動小数点の問題だろう。
指数部が10進数としての仮数部の小数点の位置を示すタイプの型。
Truncする前に既に 1359999.999... が丸まって桁が上がってるものと思われる。



91:NAME IS NULL
08/05/24 17:46:16 /or0WR4U
質問です。SQL Server 2005を使用しています。
aテーブルの行を並び替える時に
bテーブルの内容に左右されて
結果を表示したいのですが、どんなSQL文があるのでしょうか?

aテーブル
No Class Num Data
-----------------
1  A    03  data
2  A    01  data
3  A    02  data
4  B    01  data
5  B    02  data
6  C    03  data
7  C    04  data
8  C    01  data
9  C    02  data

bテーブル
Class ClassLevel
-----------------
A     2
B     3
C     1

結果
8 C 01 data
9 C 02 data
6 C 03 data
7 C 04 data
2 A 01 data
3 A 02 data
1 A 03 data
4 B 01 data
5 B 02 data

よろしくお願い致します。

92:NAME IS NULL
08/05/24 17:49:42
>>91
結合して ORDER BY

93:NAME IS NULL
08/05/24 18:31:38
検証なし。
SELECT
 A.No,
 B.Class,
 A.Num
 A.Data
 FROM
  a A,
  b B
 WHERE
  A.Class = B.Class
 ORDER BY
  B.Class,
  A.Num

INNER JOINでもいい

94:NAME IS NULL
08/05/24 18:35:44
検証なし。INNER JOIN
SELECT
 A.No,
 B.Class,
 A.Num
 A.Data
 FROM
  a A INNER JOIN b B
    ON A.Class = B.Class
 ORDER BY
  B.Class,
  A.Num

95:NAME IS NULL
08/05/24 21:08:03
>>85
あはぁん、言われるような気がしたわ

他からも指摘されてるので皆にも謝っておくわ、すまん

あんま詳しく書けんが今回はヘッダにしかない金額を明細へある比率で振り分け、余った金額は1件目に乗っけるってとこで
幸い総額は誤りがないのと明細毎で出す金額じゃないんで特に問題になってない

が、なんでこうなるのかって説明は自分もそうだが聞いてる方もついてこれんと思う



96:NAME IS NULL
08/05/24 22:15:31
>余った金額は1件目に
むかし、実際の事件で銀行の金利計算で、小数点第1位以下を全部自分の口座に送るという
プログラムを作った奴がいてな、
その発見されかたも面白いんだが、小数点以下まできっちり計算する強欲なおばあさんの指摘でわかったそうだ。

97:NAME IS NULL
08/05/24 23:09:27
サラミうめえw

98:NAME IS NULL
08/05/24 23:43:01
俺、ビーフジャーキー

99:NAME IS NULL
08/05/24 23:45:15
>95
勘定系で端数がある場合は明細サマリと総額とが合わない前提で「雑損雑役」とかに仕訳すると思われる。
無理して合わせてると却って会計担当者から指摘されそうな気が

100:NAME IS NULL
08/05/25 00:49:35
>>96
それ知ってる。
むかしかぁ、リアルタイムだったな確か。

金額が大きすぎて怖くなったと新聞に出てたんで、自首だと思ってたわ

101:NAME IS NULL
08/05/25 09:05:30
多通貨会計なシステムやっていると端数の問題はかならず出てくるんだけど、
その端数用の勘定科目を用意してちゃんと説明しないと、
監査の時にウダウダ言われる。

ただまあ、日本円だけで動いているシステムならそれくらいちゃんとヤレって希ガス

102:NAME IS NULL
08/05/25 11:47:54
>>100
あの手の事件は一回だけじゃなくて、外国とかも含めていくつかある。

103:NAME IS NULL
08/05/25 11:51:51
>>102
とてつもない金額になるんだろうね。

104:NAME IS NULL
08/05/25 18:24:36
Mysql4.0で
2008-07-31
2009-06-31
2008-10-31
というレコードがあります。
ある基準日からのこのレコードとの差分日数の合計値を割り出したいのですが、
どのようなSQL文を使えば可能でしょうか?

たとえば、基準日を2008-06-30とした場合、
上記3つのレコードの場合、求めたい答えは
2008-07-31 - 2008-06-30 = 31
2009-06-30 - 2008-06-30 = 365
2008-10-31 - 2008-06-30 = 123
で519日となります。


105:NAME IS NULL
08/05/25 19:06:59
検証なし
SELECT
DATEDIFF(expr,expr2)

106:NAME IS NULL
08/05/25 19:25:43
>>104
SUM(TO_DAYS(DateColumn) - TO_DAYS(基準日))

107:NAME IS NULL
08/05/25 19:49:54
検証なし

SELECT
SUM(A.DAYS)
FROM
(
SELECT
 DATEDIFF(:基準日,T.COL:) AS DAYS
TABLE T
)A

108:NAME IS NULL
08/05/26 13:20:37
oracle使ってます。

ID1   ID2
001   001
001   002
001   003
001   004
002   005
002   006
……   ……

という表があって、このあとID1はランダム、ID2はそのまま続きます。
その中でID1が複数ある場合を抜き出すにはどうすればいいですか?

109:NAME IS NULL
08/05/26 13:42:03
その例で言うと、実際に抜き出すとどういうデータになるの?

110:NAME IS NULL
08/05/26 23:10:38
エスパー&検証なし
SELECT
T.ID1,
T.ID2
FROM
TABLE T
HAVING COUNT(ID1) > 1

111:NAME IS NULL
08/05/26 23:25:59
「検証なし」の人の回答がほぼ毎回間違っている件

112:NAME IS NULL
08/05/26 23:31:59
発言通りじゃないですか。

113:NAME IS NULL
08/05/27 02:30:55
>>111
しかもエスパーだから手がつけられないな
スプーン曲げます!って言ったら胴体が切断されるぜ

114:NAME IS NULL
08/05/27 03:10:33
>>110
GROUP BY ...
無理に書かなくてもいいんじゃ?

115:NAME IS NULL
08/05/27 10:38:49
質問者のあいまいなところを無理やり解釈したところがエスパーなんだろうけど
答え出ないから質問者の意図した通りかも検証できないなw

116:91
08/05/27 11:33:41 98WRggUu
>>92,93,94
ありがとう!!!

117:NAME IS NULL
08/05/27 17:30:05 +iz1hIp5
MySQL

tableA
A_ID name_v1 ...
-----------
1   あいうえお
2   かきくけこ
3   さしすせそ
4   たちつてと
5   なにぬねの


tableB
B_ID name_v2 A_ID_copy ...
-----------
1  カキクケコ 2
2  ナニヌネノ 5
3  アイウエオ 1
4  タチツテト 4
5  サシスセソ 3

A_ID は A_ID_copyと対応しています。
tableA.name_v1をlike %検索文字列% で絞込みし、それに対応したIDのものだけをtableBから引っ張りたいのですが
実際に何か文字列を入れて走らせると関係のないレコードまで引っかかってしまいます。

すぐに思いついたのは次です。 ついでにname_v1も欲しいのでそれも加えてあります。
select
  tableB.B_ID, tableB..... (select tableA.name_v1 from member where tableA.A_ID = tableB.B_ID) as A_name
from
  tableA, tableB
where
  tableA.name_v1 like '%検索文字列%'
;

神様ご教示お願いします。


118:NAME IS NULL
08/05/27 17:37:58
文字コードの設定どうなってる?

119:NAME IS NULL
08/05/27 18:00:23 +iz1hIp5
>>118
OSは近年のFedoraでecho $LANGするとja_JP.UTF-8

MySQLのmy.cnfにもdefault-character-set=utf-8

PHP(SymfonyのCriteria)から叩いていますが、php.iniはちょっと怪しい
;mbstring.language = Japanese
;mbstring.internal_encoding = UTF-8
;mbstring.http_input = auto
;mbstring.http_output = Shift_JIS
mbstring.encoding_translation = On
mbstring.detect_order = auto
;mbstring.substitute_character = none;
mbstring.func_overload = 0
mbstring.strict_encoding = On

怪しいとはいえ、Criteriaにぶち込む直前の検索文字列の文字コードを出力
したらUTF-8と出ました。

また、tableB.name_v2をlike '%ほげ%' で検索している処理はうまく動いているので
文字コードは大丈夫なんじゃないかと。 後だし情報失敬。

120:NAME IS NULL
08/05/27 18:30:18
>A_ID は A_ID_copyと対応しています。
>tableA.name_v1をlike %検索文字列% で絞込みし、それに対応したIDのものだけをtableBから引っ張りたいのですが

これだけだったら
select B_ID from tableB as B inner join tableA as A on (A.A_ID = B.A_ID_copy)
where (A.name_v1 like '%検索文字列%')
だけの話だと思うが、何故にサブクエリ…

121:NAME IS NULL
08/05/27 18:49:19
select * from tableB where A_ID_copy in (select A_ID from tableA where name_v1 like '%検索文字列%')
むしろこうするけどな。


122:NAME IS NULL
08/05/27 20:07:39
>>121
コスト意識しようぜ

123:NAME IS NULL
08/05/27 21:07:58 +iz1hIp5
>>120-122
ありがとうございます。
明日会社に着き次第試してみます。


124:NAME IS NULL
08/05/27 21:18:37
>>122
え?>>120>>121はlikeで複数レコードにマッチした場合の挙動違うよ。
distinctつけないと同じにはならないし、求める結果はdistinct付きのほうでしょ?
そうするって事はソートのコストがかかるよね?

125:NAME IS NULL
08/05/27 21:32:50
と思ったが、Bの内容も抽出したいのね。俺がバカでした。

126:NAME IS NULL
08/05/27 21:33:56
Aだし。吊ってくるorz

127:NAME IS NULL
08/05/27 21:41:58
何が言いたいのかよく分からんが
select B.* from tableB as B inner join tableA as A on A.A_ID = B.A_ID_copy where A.name_v1 like '%検索文字列%'

select * from tableB where A_ID_copy in (select A_ID from tableA where name_v1 like '%検索文字列%')
は一緒だろ?
後者のほうが遅そうってのは確かだけど。

ちなみに前者より
select B_ID from tableB as B inner join (select A_ID from tableA where name_v1 like '%検索文字列%') as A on A.A_ID = B.A_ID_copy
のほうがさらに速いかもしれん。(変わらんかもしれん。)

128:123
08/05/28 13:48:53
試してみました。
どれも何とか使えそうです。
今回は>>120のを改変して使わせていただきます。

データが数件しかないのであまり参考になりませんが、
>>121のが、他のクエリよりも5〜10msほど遅いようです。
>>120>>127の三つ目はほとんど変わらないっぽい。

本当に助かりました。
ありがとうございます。

129:NAME IS NULL
08/05/28 15:02:12
>>128
Aの複数レコードにマッチするような検索してみるとどうなる?
%だけでもいいけど。

130:NAME IS NULL
08/05/28 19:28:04
下記2種のテーブルを使い、
期間を指定してID毎に、上半期(1〜6月)の合計、下半期(7〜12月)の合計を
実行結果のような感じで表示させたいですがどうすればよいでしょうか?
勉強始めてつまってしまいました。
オラクルです

■SYAIN TABLE
----------------
ID NAME
----------------
1 aaaa
2 iiii
3 uuuu
4 eeee

■JUCHUU TABLE
---------------------------
ID YEAR MONTH SAL
---------------------------
1 2000 4 1000
1 2000 4 2000
1 2000 8 1500
2 2000 4 1000
2 2000 8 1000
3 2000 1 1000
4 2001 2 2000
4 2002 7 1000
5 2008 12 2000

■実行結果
-----------------------------------------
ID NAME KAMIHANKI SIMOHANKI
---------------------------------------
1 aaaa 3000 1500
2 iiii 1000 1000
3 uuuu 2000
4 eeee 2000 1000



*期間を指定してID毎に合計することはできました。

SELECT SYAIN.ID , SYAIN.NAME,
SUM(JUCHUU.SAL)
FROM SYAIN LEFT JOIN JUCHUU ON SYAIN.ID = JUCHUU.ID
WHERE (YEAR||LPAD(MONTH,2,0)) >= 20001
AND (YEAR||LPAD(MONTH,2,0)) <= 200501
GROUP BY SYAIN.ID,SYAIN.NAME,SYAIN.BUSHO_ID,JUCHUU.YEAR,JUCHUU.MONTH

----------------------------
ID NAME SUM(JUCHUU.SAL)
------------------------------
1 aaaa 4500
2 iiii 2000
3 uuuu 1000
4 eeee 3000


131:NAME IS NULL
08/05/28 19:40:05
>>130
>>4

132:NAME IS NULL
08/05/28 20:18:57
さすがに>>4だけじゃアレなんでもう少しヒント:
sum(case when MONTH <= 6 then SAL else 0 end) as KAMIHANKI

ところで例えば2000年の上期と2001年の上期は足すんか?

あと、その例だとLEFT JOINはINNER JOINでも一緒。
(そのWHERE句だとJUCHUU側がNULLのものは消えちゃう。)
それと、GROUP BY書きすぎ。

133:NAME IS NULL
08/05/28 22:25:05
検証有り(MS)
期間指定せず、社員毎年毎半期毎の合計値
SYAINは適当にinner joinしてくれ

SELECT
 T.ID,
 T.YEAR,
 SUM(T.KAMIHANKI) AS KAMIHANKI,
 SUM(T.SIMOHANKI) AS SHIMOHANKI
FROM
(
  SELECT
    J.ID,
    J.YEAR,
    CASE WHEN J.MONTH < 6 THEN SUM(J.SAL) ELSE 0
    END KAMIHANKI,
    CASE WHEN J.MONTH > 6 THEN SUM(J.SAL) ELSE 0
    END SIMOHANKI
   FROM JUCHUU J
   GROUP BY
    J.ID,
    J.YEAR,
    J.MONTH
 )T 
 GROUP BY
  T.ID,
  T.YEAR


134:NAME IS NULL
08/05/28 23:12:13
検証ありでも間違っている件

135:NAME IS NULL
08/05/29 00:46:09
あってんじゃね?

136:NAME IS NULL
08/05/29 00:56:27
ヒント:6

137:NAME IS NULL
08/06/01 00:12:33
上半期でも下半期でもない6月になりましたよ。

138:NAME IS NULL
08/06/01 00:17:00
6月のことはなかったことに

139:NAME IS NULL
08/06/01 15:31:08
ID | NAME | OLD_ID
--+-----+------
1 | taro  | 0    
2 | jiro   | 1    
3 | saburo | 2    
4 | shiro  | 0    
5 | goro   | 3    

上のようなテーブルから、以下のように
OLD_IDが0でなければ、OLD_IDに対応するNAMEを出力
OLD_IDが0ならば、かわりに(たとえば)空白文字を出力

a.ID | a.NAME | a.OLD_ID | b.NAME
---+-------+-------+---------
1   | taro    | 0     | ""
2   | jiro     | 1     | taro
3   | saburo  | 2     | jiro
4   | shiro   | 0     | ""
5   | goro    | 2     | jiro

というSQL文を作りたいのですが、どのように分岐させたらよいでしょうか。
環境はMySQL5.0です。よろしくお願い致します。

140:NAME IS NULL
08/06/01 15:33:39
>>139
元の表を訂正

ID | NAME | OLD_ID
--+-----+------
1 | taro  | 0    
2 | jiro   | 1    
3 | saburo | 2    
4 | shiro  | 0    
5 | goro   | 2 ←3ではなく2でした

141:NAME IS NULL
08/06/01 16:15:15
>>139
case

142:NAME IS NULL
08/06/01 16:36:48
検証なし。
MySQLは使ったことが無い。
NVL、ISNULLに対応するのがIFNULLらしい。

SELECT
  T1.ID,
  T1.NAME,
  T1.OLD_ID,
  IFNULL(T2.NAME,'')
 FROM
 TABLE T1 LEFT JOIN TABLE T2 ON
 T1.OLD_ID = T2.ID

143:NAME IS NULL
08/06/01 16:56:03
>>142
nullじゃなくて「0」。

case T1.OLD_ID when '0' then '' else T2.NAME


144:NAME IS NULL
08/06/01 17:00:34
>>142
> MySQLは使ったことが無い。

それ以前に、回答するレベルじゃない。

JOIN が必要かどうか >>139 をちゃんと読み直すように。

145:NAME IS NULL
08/06/01 17:04:09
JOIN は必要だろ?

146:NAME IS NULL
08/06/01 17:34:45
JOINは要るな。つーかこういうケースは>>142で十分じゃね?
何かの間違いでIDが0のレコードが入らない限りは


147:>>145
08/06/01 17:41:15
>>142, >>145-146
ああすまん、全然勘違いしてた。m(_._)m

148:>>144
08/06/01 17:43:02
名前欄間違ってるし... orz
>>145>>144

149:NAME IS NULL
08/06/01 18:56:37
>>141-148
>>142さんのSQL文で動きました
どうもありがとうございました

150:NAME IS NULL
08/06/01 20:24:16
>>144

151:NAME IS NULL
08/06/01 21:07:03
アッー!

152:NAME IS NULL
08/06/03 19:41:01
1から研修中の者です。

先輩同士が、SUMをかけるか否かという話をしている時に、
「かけてもかけなくても結果は同じだろうし、
主キーとの関係から考えても、このカラムはGROUP byに入れない方がいい」と言っているのを盗み聞きました。

主キーとGROUP化との関連なんてあるんですか?
盗み聞いたもので、情報も少ない上、先輩にも聞けなくて困ってます。

153:NAME IS NULL
08/06/03 19:49:45
>>152
予想されることはいくつかあるが、ここで聞くには情報不足。
その先輩とやらに確認して来い。

154:152
08/06/03 19:56:48
>>153
そこを何とか・・・。
ヒントとか、キーワードだけでいいんで、お願いします・・・。
先輩と言っても、完全な自社の人じゃなくて、
ちょっと聞きにくすぎます・・・。

155:NAME IS NULL
08/06/03 20:24:29
>>152
情報が少ないんでしょ?で、こっちは研修内容すら知らないわけで、
>>152よりも情報が少ない状態だ。
それでなにをどうすればいいんだ?
SUMをかけるか否かという議論に対して、どちらでも結果は同じって
意見が出るような元の状態が把握できない。


次ページ
最新レス表示
スレッドの検索
類似スレ一覧
話題のニュース
おまかせリスト
▼オプションを表示
暇つぶし2ch

4937日前に更新/155 KB
担当:undef