2ちゃんねる スマホ用 ■掲示板に戻る■ 全部 1- 最新50    

■ このスレッドは過去ログ倉庫に格納されています

SQL質疑応答スレ 16問目

1 :NAME IS NULL:2015/11/10(火) 22:07:38.40 ID:???.net
このスレは
「こういうことをやりたいんだけどSQLでどう書くの?」
「こういうSQLを書いたんだけどうまく動きません><」
などの質問を受け付けるスレです。

SQLという言語はISOによって標準化されていますが
この標準を100%実装したDBMSは存在せず、
また、DBMSによっては標準でない独自の構文が
追加されていることもあります。

質問するときはDBMS名を必ず付記してください。

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

前スレ:
SQL質疑応答スレ 15問目
http://peace.2ch.net/test/read.cgi/db/1402919549/

2 :NAME IS NULL:2015/11/10(火) 22:09:00.55 ID:???.net
SQL言語リファレンス一覧
Oracle Database
http://docs.oracle.com/cd/E57425_01/121/SQLRF/toc.htm
Microsoft SQL Server
http://msdn.microsoft.com/ja-jp/library/bb510741
IBM DB2 Database
http://pic.dhe.ibm.com/infocenter/db2luw/v10r5/topic/com.ibm.db2.luw.sql.ref.doc/doc/c0004100.html

PostgreSQL
http://www.postgresql.jp/document/current/html/sql.html
MySQL
http://dev.mysql.com/doc/refman/5.7/en/sql-syntax.html
http://dev.mysql.com/doc/refman/5.6/ja/sql-syntax.html


参考リンク
http://sql.main.jp/cont/sql/map.html
http://www.atmarkit.co.jp/fnetwork/rensai/sql01/sql1.html
http://www.geocities.jp/oraclesqlpuzzle/
http://www.techscore.com/tech/sql/

3 :NAME IS NULL:2015/11/10(火) 22:10:13.52 ID:???.net
過去スレ
15問目:http://peace.2ch.net/test/read.cgi/db/1402919549/
14問目:http://peace.2ch.net/test/read.cgi/db/1371476534/
13問目:http://toro.2ch.net/test/read.cgi/db/1343899481/
12問目:http://toro.2ch.net/test/read.cgi/db/1316769778/
11問目:http://hibari.2ch.net/test/read.cgi/db/1299305530/
10問目:http://hibari.2ch.net/test/read.cgi/db/1274791771/
9問目:http://pc11.2ch.net/test/read.cgi/db/1252492296/
8問目:http://pc11.2ch.net/test/read.cgi/db/1236253554/
7問目:http://pc11.2ch.net/test/read.cgi/db/1223525474/
6問目:http://pc11.2ch.net/test/read.cgi/db/1210940477/
5問目:http://pc11.2ch.net/test/read.cgi/db/1193486961/
4問目:http://pc11.2ch.net/test/read.cgi/db/1176553195/
3問目:http://pc11.2ch.net/test/read.cgi/db/1160458216/
2問目:http://pc8.2ch.net/test/read.cgi/db/1141622643/
帰ってきた:http://pc8.2ch.net/test/read.cgi/db/1124178925/
Part 2:http://pc8.2ch.net/test/read.cgi/db/1103113155/
初代:http://pc8.2ch.net/test/read.cgi/db/1056973582/

4 :NAME IS NULL:2015/11/10(火) 22:11:19.91 ID:???.net
よくある質問1

(問)
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
;

5 :NAME IS NULL:2015/11/10(火) 22:12:29.80 ID:???.net
よくある質問2

(問)
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
;

6 :NAME IS NULL:2015/11/10(火) 22:13:39.32 ID:???.net
よくある質問3

(問)
ID HOGE
01 A
01 B
01 C
02 A
03 B

HOGEをAもBもCも持っている、ID:01だけ取り出すにはどうすればよかですか

(答1)
SELECT id
FROM TableName
WHERE hoge in ('A','B','C')
GROUP BY id
HAVING count(DISTINCT hoge) = 3
;

(答2)
select *
from TableName T1
where not exists (select *
         from (values 'A', 'B', 'C') T2 (HOGE)
         where not exists (select *
                  from TableName T3
                  where T1.ID = T3.ID
                  and T2.HOGE = T3.HOGE
                  )
         )
;
※valuesの部分(Table Value Constructor)はDBMSによって文法がかなり違うので注意

7 :NAME IS NULL:2015/11/10(火) 22:14:51.52 ID:???.net
よくある質問4

(問)
列の数が可変な問合せはどう書きますか?

(答)
標準SQLでは書けません。
pivotという機能を搭載したDBMSなら一見書けそうですが実はやっぱり書けません。
Oracle 11g以降でpivot xmlというキーワードを使用すれば一応可変っぽくはなります。
が、素直にプロシージャを書くかアプリケーションで処理したほうが良いでしょう。

SQL Serverのpivot(2005以降)
http://msdn.microsoft.com/ja-jp/library/ms177410.aspx

Oracleのpivot(11g以降)
http://download.oracle.com/docs/cd/E16338_01/server.112/b56299/statements_10002.htm#CHDCEJJE
http://www.oracle.com/technetwork/articles/sql/11g-pivot-097235.html

8 :NAME IS NULL:2015/11/10(火) 22:16:01.06 ID:???.net
よくある質問5

(問)
年月(YYYYMM)を指定し、その年月に対応する年月日を取得したい

 例:201006を指定したら、以下の結果を得たい

   20100601
   20100602
    ・
    ・
    ・
   20100630

(答)
SQLでは存在しないデータを生成することはできません。
この問いの場合は素直にカレンダーテーブルを用意しましょう。

どうしてもやりたければ以下のような方法もなくはないですが、
再帰問合せの本来の使い方ではありません。
やめておくことを強くお奨めします。
(PostgreSQLのgenerate_series()関数なら辛うじてセーフかもしれませんが
 賛否の分かれるところでしょう。)

with TEMP (NUM) as (
    select 1 from dual
    union all
    select NUM + 1 from TEMP where NUM < 31
)
select to_char(to_date('201006', 'YYYYMM') + NUM - 1, 'YYYYMMDD')
from TEMP
where to_date('201006', 'YYYYMM') + NUM - 1 < add_months(to_date('201006', 'YYYYMM'), 1)
;

※上記はOracleの場合です。(11gR2以降)
※再帰問合せをサポートするDBMSならこれを適当に改変すれば動きますが
 どのみちお奨めしません。

9 :NAME IS NULL:2015/11/10(火) 22:25:16.15 ID:???.net
以上、テンプレ終わり

10 :NAME IS NULL:2015/11/11(水) 00:11:34.95 ID:???.net
文字列でバージョン情報を格納してるカラムがあるんですけど、
これをうまく並べ替えれないですかね?

3.12.1
3.8.1

こういう二つのバージョンがあった場合、文字列ソートだから後者の方が大きいと判定されてしまうんですよね。
やっぱりバージョンのドット毎に区切った数字をカラムに保存して、ソートするしかないでしょうか?

11 :NAME IS NULL:2015/11/11(水) 18:51:31.29 ID:???.net
難しいな、、、
ピリオドの数固定なら
PostgreSQLだと split_part() と lpad() 組み合わせてなんとかなったけど

12 :NAME IS NULL:2015/11/11(水) 19:18:28.66 ID:???.net
自分なら邪道だけど、文字列のカラムに加えて、ソート用にバラした整数のカラムを追加するかな...

ver_raw = '1.23.4'
ver_mj = 1
ver_mi = 23
ver_se = 4

てな感じに。これだと "2.11.5_revB" みたいな変なものがきても、格納はできる。

13 :NAME IS NULL:2015/11/11(水) 20:17:19.69 ID:???.net
http://i.imgur.com/UFmYAuK.jpg

14 :NAME IS NULL:2015/11/13(金) 17:41:51.54 ID:???.net
【質問テンプレ】
・DBMS名とバージョン
MariaDB 10.0.21

・テーブル
ID,DATA,col1,col2,col3

・説明
SELECT ID, DATA AS DATA_A FROM table WHERE col1 = 100 AND col2 = 2 AND col3 = 0;

SELECT ID, DATA AS DATA_B FROM table WHERE col1 = 100 AND col2 = 3 AND col3 = 0;

SELECT ID, DATA AS DATA_C FROM table WHERE col1 = 100 AND col2 = 4 AND col3 = 0;

col1,col2.col3の内容によって、DATAカラム内の意味が変わってくるテーブルです。
上記3つのSQLの結果を以下の用に一行でまとめたいです。

ID,DATA_A,DATA_B,DATA_C

このような事は可能でしょうか?
UNIONやgroup byでは厳しそうなので相談させてください。

宜しくお願いします。

15 :NAME IS NULL:2015/11/13(金) 17:50:20.53 ID:???.net
これってA、B、Cそれぞれ1行しか無いの?

16 :NAME IS NULL:2015/11/13(金) 17:57:57.53 ID:???.net
イメージ的にはこんなかんじにしたいです。

ID | DATA | col1 | col2 | col3
--+-----+-----+---+-----------
1 | aaa | 100 | 2 | 0
1 | bbb | 100 | 3 | 0
3 | ccc | 100 | 3 | 0
2 | ddd | 100 | 2 | 0
2 | eee | 100 | 4 | 0
3 | fff | 100 | 2 | 0



ID | DATA_A | DATA_B | DATA_C
---+--------+--------+------
1 | aaa | bbb | 0
2 | ddd | 0 | eee
:
:

17 :NAME IS NULL:2015/11/13(金) 18:09:42.07 ID:???.net
よくわからんけどorでくっつけりゃいけるんじゃ

18 :NAME IS NULL:2015/11/13(金) 19:26:16.88 ID:???.net
>>14
>>5のsum()のかわりにgroup_concat()を使う

19 :NAME IS NULL:2015/11/13(金) 23:13:15.96 ID:???.net
>>14
> col1,col2.col3の内容によって、DATAカラム内の意味が変わってくるテーブルです。

あんさんが書いた内容だと、col1 は 100、col3 は 0 固定なんだが
とりあえず col2 で変わると言うことか?

そもそも >>16 見ると ID でまとめてる様に見えるし
データがないところに NULL じゃなくて 0 を入れればいいのか?
ID と col2 が同じレコードは複数ないのが前提なのか?

20 :NAME IS NULL:2015/11/14(土) 17:56:40.28 ID:???.net
【質問テンプレ】
・DBMS名とバージョン
Oracle 11gR2

・テーブルデータ
table_a
id parent_id
---- ---------
1 null
11 1
111 11
1111 111
1112 111
2 null
22 2
222 22
23 2
223 23
224 23

table_b
id cost
---- ---------
1111 100
1112 200
222 300
223 400
224 500

・欲しい結果
id SUM(cost)
---- ---------
1 300
11 300
111 300
1111 100
1112 200
2 1200
22 300
222 300
23 900
223 400
224 500

・説明
table_aはid - parent_idで階層になっている。
table_aの階層毎にtable_bのcostの集計値を表示させたい。
階層の深さは一定ではない。

21 :NAME IS NULL:2015/11/14(土) 21:10:35.03 ID:???.net
こうかな?

with cum (id, parent_id, cum_cost) as (
    select t1.id,
        t1.parent_id,
        coalesce(t2.cost, 0)
    from  table_a t1
        left outer join
        table_b t2
        on t1.id = t2.id
    where not exists (
        select *
        from  table_a t3
        where  t1.id = t3.parent_id
    )
    union all
    select t4.id,
        t4.parent_id,
        coalesce(t6.cost, 0) + t5.cum_cost
    from  table_a t4
        inner join
        cum t5
        on   t4.id = t5.parent_id
        left outer join
        table_b t6
        on   t4.id = t6.id
)
select id,
    sum(cum_cost)
from  cum
group by id
order by to_char(id)
;

22 :NAME IS NULL:2015/11/15(日) 00:46:14.76 ID:???.net
>21 ありがとうございます。
今現在環境がないので、月曜日に試してみます。

23 :NAME IS NULL:2015/12/01(火) 19:58:51.94 ID:???.net
お願いします

■PostgreSQL 9.4

■テーブルデータ
id|price|created_at
------------------
1|500|2015-11-01 00:00:00.00000+09
2|500|2015-11-31 00:00:00.00000+09
3|300|2015-12-01 10:00:00.00000+09
4|500|2015-12-01 20:00:00.00000+09
5|400|2015-12-02 15:00:00.00000+09

■欲しい内容
2015年12月のレコードからpriceのみがほしい。
同じ日付のpriceを全て足した状態でほしい。
800←1日の300+500
400←2日の400

24 :NAME IS NULL:2015/12/02(水) 00:26:39.36 ID:???.net
select to_char(created_at,'YYYY-MM-DD') as day,sum(price) from tablename
where created_at between '2015-12-01 00:00:00' and '2015-12-31 23:59:59'
group by day order by day ;

日付はいらないのかな・・

25 :NAME IS NULL:2015/12/02(水) 01:18:28.41 ID:???.net
>>23
ご指摘されてから日付も必要だと気づきました
試してみてうまくいきました
ありがとうございます

26 :NAME IS NULL:2015/12/02(水) 06:56:53.70 ID:???.net
>>24
'2015-12-31 23:59:59.00001' ~ '2015-12-31 23:59:59.99999' のデータを取りこぼしちゃう…

27 :NAME IS NULL:2015/12/02(水) 13:00:04.86 ID:???.net
適当に直してくださいw

28 :NAME IS NULL:2015/12/21(月) 18:32:01.84 ID:???.net
【質問テンプレ】
・DBMS名とバージョン
Oracle 12c

・テーブルデータ
employees表には名前(employee_name)、給与(salary)が入っています。
grade表には、grade列、low列、high列があり
各gradeの範囲が格納されています。

・質問
下記、最高給与の従業員名と給与、給与等級を表示するSQL文です。
「salary = (SELECT MAX(salary) FROM employees)」、「salary BETWEEN low AND high 」
のどちらが検索条件で、どちらが結合条件でしょうか

SELECT employee_name, salary, grade FROM employees, grade  
WHERE salary = (SELECT MAX(salary) FROM employees)
AND salary BETWEEN low AND high

29 :NAME IS NULL:2015/12/21(月) 20:03:59.26 ID:6czbpcbH.net
>>28
後者。

何この質問?

宿題?

30 :NAME IS NULL:2015/12/21(月) 20:04:56.43 ID:6czbpcbH.net
後者が結合条件。

31 :NAME IS NULL:2015/12/21(月) 20:11:18.81 ID:???.net
詳しく言えば非等価結合な。

32 :NAME IS NULL:2015/12/21(月) 21:10:08.83 ID:ozDeyBqI.net
思うんだけど、入門者に対して最初からこういった(専門)用語を学ばせる(覚えさせる)ってのはどうなんだろうな?
こんな用語知らなくても実務じゃ問題なかろう

33 :NAME IS NULL:2015/12/22(火) 03:57:36.25 ID:???.net
結合させるためのものか検索するためのものかは用語を知らずとも判断できるはずだよね。
そして少なくとも今回の場合、用語がどちらに当てはまるものかはきわめて容易に分かるよね。
その上で>>32のレスを書いたということ?

34 :NAME IS NULL:2015/12/22(火) 07:03:32.73 ID:???.net
>>32
普通にここの検索条件見直せとか言うだろ
くそ忙しい時に検索条件ってどれですかぁ?
なんて間抜けなこと聞かれたらブチ切れられて当然だと思う

35 :NAME IS NULL:2015/12/22(火) 10:50:38.89 ID:???.net
暇でない人間は2チャンネルなんか見に来ないよ

36 :NAME IS NULL:2015/12/22(火) 11:41:35.78 ID:???.net
それ、一連のやり取りに関係ある?
ただの捨て台詞だよね?

37 :NAME IS NULL:2015/12/22(火) 11:45:56.45 ID:???.net
職場で聞かれているわけじゃないんだから、
そういうシチュエーションはいらないと思います。

38 :NAME IS NULL:2015/12/22(火) 12:53:03.62 ID:???.net
データベースの構成についての質問もここでいいですか?

39 :38:2015/12/22(火) 12:54:41.62 ID:???.net
訂正
テーブル構造の質問です

40 :NAME IS NULL:2015/12/22(火) 13:33:42.07 ID:???.net
DB設計を語るスレ 9
http://peace.2ch.net/test/read.cgi/db/1444733172/

とかどう?

41 :NAME IS NULL:2015/12/22(火) 19:49:10.84 ID:???.net
>>37
>>32 > こんな用語知らなくても実務じゃ問題なかろう
                  ̄ ̄ ̄ ̄
まあ、DB回りは俺一人で開発してる
とかなら知らんが

42 :NAME IS NULL:2015/12/22(火) 19:53:13.39 ID:???.net
その人がどういう環境でSQLを使おうとしているかをまず聞いた上でなら分かるけど
実務で使うかどうかすら聞いてないんでしょ?

43 :NAME IS NULL:2015/12/22(火) 20:46:53.76 ID:???.net
その無益な言い合いどうでもいいです
何か書き込みあったかと思って見てみれば…

44 :NAME IS NULL:2015/12/22(火) 20:57:56.09 ID:???.net
>>42
その人がどの人か知らんけど、俺は >>32 にレスしてるだけ

45 :NAME IS NULL:2015/12/22(火) 21:03:24.88 ID:???.net
>>34
実務でそんな話が出たらWHERE句全体のことかと思いそうだが。
>>28の検索条件と結合条件って実際呼び分けてる?

46 :NAME IS NULL:2015/12/22(火) 21:06:02.81 ID:???.net
そうですか。では私の発言は無視して下さい。

47 :NAME IS NULL:2015/12/22(火) 21:24:17.70 ID:???.net
>>45
呼び分けてない

48 :NAME IS NULL:2015/12/22(火) 22:26:22.87 ID:+RAFY3WQ.net
>>45
結合条件と絞込条件

俺は検索条件というあいまいな言葉は使わないな。

49 :NAME IS NULL:2015/12/22(火) 22:59:18.71 ID:???.net
FROM句のテーブルを直積→WHERE句の条件で絞込み(選択)、ってイメージだから
区別したことないわ。

50 :NAME IS NULL:2015/12/22(火) 23:44:03.90 ID:+RAFY3WQ.net
>>49
FROM句で結合条件を書く方法だとそれでいい。

WHERE句で書く場合は、結合条件と絞込条件が混在するので、先に結合条件を書いたり、コメントを入れる。

51 :NAME IS NULL:2015/12/23(水) 00:07:47.91 ID:???.net
逆だろ。FROM句にJOINで結合条件書いたらそれは直積じゃない。
で、直積に対しては結合条件と絞込条件などと区別する必要もない。

52 :NAME IS NULL:2015/12/23(水) 00:18:40.85 ID:???.net
>直積に対しては結合条件と絞込条件などと区別する必要もない。
あのさあ

53 :NAME IS NULL:2015/12/23(水) 00:35:24.51 ID:???.net
>>52
なになに?

54 :NAME IS NULL:2015/12/23(水) 00:38:52.62 ID:???.net
>>50
&#9747;FROM句で結合条件を書く方法だとそれでいい
○FROM句に結合条件書かないならそれでいい

だよな?書き間違い?

55 :NAME IS NULL:2015/12/23(水) 00:56:59.80 ID:???.net
>>53
上を見て納得しました
絡んですいません

56 :NAME IS NULL:2015/12/23(水) 01:27:59.83 ID:???.net
http://q.hatena.ne.jp/1327717990

このページのうぃんどさんが偉そうに説明してる全結合ってどこの用語?
StackOverFlow 見ると explain させて where も inner join もどっち使っても一緒って切り捨てられてるみたいだけど

57 :NAME IS NULL:2015/12/23(水) 09:55:42.49 ID:???.net
>>54
たぶん>>50は直積を知らなくて、>>49がJOINのことを言っていると脳内変換したと思われ

58 :38:2015/12/23(水) 18:06:16.42 ID:???.net
>>40
質問を整理してからそこで聞いてきます

59 :NAME IS NULL:2015/12/27(日) 12:35:10.49 ID:???.net
教えてください。

やりたいこと
・元のデータ(生データ)を格納する table A がある
・生データを週単位で集計した table B がある
・新たな生データを投入した table A' を集計して集計済みの table B のデータに加えたい

単純に A' のデータを集計して B に新規追加するだけなら簡単なのですが、
A' のデータと同じ集計単位のデータが B にあった場合にどう処理するのが効率的なのかが分かりません。
A' のデータを一端一時テーブル等に集計した後に、B に存在する集計単位と存在しない集計単位ごとに
UPDATE と INSERT を行う方法が思いつくのですが、一般的でしょうか。

アドバイスを頂ければ、と思います。

60 :NAME IS NULL:2015/12/27(日) 13:08:20.26 ID:yu7sfdbc.net
>>59
質問が分かりません。

61 :NAME IS NULL:2015/12/27(日) 13:42:43.76 ID:9lnqXFiU.net
いるよな、こういう質問のドヘタクソな奴

62 :NAME IS NULL:2015/12/27(日) 14:00:57.58 ID:???.net
>元のデータ(生データ)を格納する table A がある

table Aの定義を明らかにしなさい。

>生データを週単位で集計した table B がある

何をキーに集計するのかを明らかにしなさい。

>新たな生データを投入した table A'

「新たなデータ」なら同じ集計単位は発生しないんじゃないの?

63 :NAME IS NULL:2015/12/27(日) 14:15:05.30 ID:???.net
■PostgreSQL 9.4

■テーブルデータ
id|price|created_at
------------------
1|100|2015-11-17 00:00:00.00000+09
2|200|2015-11-24 00:00:00.00000+09
3|300|2015-12-01 10:00:00.00000+09
4|350|2015-12-01 13:00:00.00000+09
5|400|2015-12-08 20:00:00.00000+09
6|500|2015-12-15 15:00:00.00000+09

今日は12/15とします。
今日の曜日を含めて過去4週分の平均を求めるSQLを教えてください。
上のテーブルだとidが2〜6までの200+(300+350)+400+500を足して4で割った値が欲しいです

64 :59:2015/12/27(日) 14:45:24.34 ID:???.net
具体的な質問じゃなくてごめんなさい。
ここは SQL 文そのものの質問をするところだったのね。スレチだし答えられなければ無視しといてください。

>「新たなデータ」なら同じ集計単位は発生しないんじゃないの?

例えば過去に 2015/11/01 のデータを投入するとそのデータが table B に保存される。
その後で 2015/11/02 のデータを投入すれば「同じ週」なので同じ集計単位のデータが発生します。

65 :NAME IS NULL:2015/12/27(日) 14:53:32.86 ID:???.net
>>64
同一日付のデータはテーブルAから弾いていいの?それとも別データ扱い?
テーブルBでは弾いていいの?それとも後から来たデータで更新したいの?

DBMS名も言った方がいいよ。やりたいことさえはっきりすれば方法はあると思う。

66 :59:2015/12/27(日) 15:21:14.83 ID:???.net
>>62,65
仮定の話になるので不要と思っていましたが、データの具体例を挙げます。

table A
id       int
custom_id  int
date      datetime
parts_id    varchar(10)
parts_count int

table B
date      datetime
parts_id    varchar(10)
parts_count int

////

table A'
11,1,2015/11/03,'partA'.1
12,1,2015/11/04,'partB'.1
13,2,2015/11/05,'partA'.2

table B
2015/01,'partA',1

table B
2015/01',partA',4
2015/01,'partB',1


この例では parts_id ごとの parts_count の合計値を週ごとに取得する。
table B の date はその週の始めの日付(日曜日)の日付を設定。
「↓」の下の B の parts_count の値は、「↓」の上の A' と B の part_id ごとの合計値。
partA では A' の合計 3 と B の 1 との合計の 4 となる。

>同一日付のデータはテーブルAから弾いていいの?それとも別データ扱い?
同一日付というか、同じ週のデータは合計します。
DBMS は特定のものを想定していませんでしたが、SQLServer2014 で試します。

67 :59:2015/12/27(日) 15:24:48.58 ID:???.net
訂正

table A'
11,1,2015/11/03,'partA'.1
12,1,2015/11/04,'partB'.1
13,2,2015/11/05,'partA'.2

table B
2015/11/01,'partA',1

table B
2015/11/01,'partA',4
2015/11/01,'partB',1

68 :NAME IS NULL:2015/12/27(日) 15:45:31.96 ID:???.net
よかった何言ってるのかわからなかったのは俺だけじゃなかったんだw

69 :NAME IS NULL:2015/12/27(日) 20:38:14.45 ID:???.net
>>59,66
知りたいのはMERGE文じゃない?
大体のDBMSで似た様なものがあるけど

70 :NAME IS NULL:2015/12/27(日) 20:41:07.29 ID:???.net
>>66
SQL Serverの場合、mergeというステートメントが使用できる。
これ使うと、対象テーブルに対して、特定条件でinsertとupdateの何れかを実行できるそうだ。
申し訳ないが、こちらには実行環境がないので実際に試しての検証はできない。

71 :NAME IS NULL:2015/12/27(日) 21:26:06.33 ID:???.net
>>69-70
欲しかったのはこれです。
ありがとうございます。

こんな感じでしょうか。(書いただけです。全く確認してません。)

MERGE INTO tableB t1
USING
 (
  SELECT DATEADD( day, ( DATEPART( date ) - 1 ) * -1, date ) AS week, parts_id, sum( parts_count ) AS parts_count
  FROM tableA'
  GROUP BY week, parts_id
  ) t2 ON t1.date = t2.week AND t1.parts_id = t2.parts_id
WHEN MATCHED THEN
 UPDATE SET t1.parts_count = t1.parts_count + t2.parts_count
WHEN NOT MATCHED THEN
 INSERT VALUES ( t2.week, t2.parts_id, t2.parts_count )

思いつきで書いただけなのでもっと効率のいい書き方がいくらでもありそう。考えます。

72 :NAME IS NULL:2015/12/28(月) 12:48:32.72 ID:jyNPkj4+.net
>>71
ロジック書いた方がいい。

メンテナンスが難しくなる。

73 :NAME IS NULL:2015/12/28(月) 14:17:09.48 ID:???.net
>>63
SELECT avg(price_total)
FROM
(SELECT
SUM(price) AS price_total
FROM
table
WHERE created_at::DATE BETWEEN '2015-12-15'::DATE + '-4 weeks'::INTERVAL + '1 day'::INTERVAL AND '2015-12-15'::DATE
GROUP BY
TO_CHAR(DATE_TRUNC('day', created_at),'YYYY-MM-DD')) foo

とかどうかなあ、4週だと11/17が入ってしまうようなので1足した
この辺は調整してみて
2015-12-15はCURRENT_TIMESTAMP とかで

74 :NAME IS NULL:2015/12/28(月) 14:20:06.57 ID:???.net
週でわけるなら
TO_CHAR(created_at,'YYYY-MM/w')
か、でもこれ起点が1日だからな

75 :NAME IS NULL:2015/12/28(月) 15:21:10.21 ID:???.net
当日から日付までの日数引いて7で割るのがよさげ

76 :NAME IS NULL:2015/12/28(月) 15:48:22.89 ID:???.net
>>72
> ロジック書いた方がいい。
ロジックって何?
クライアントループしろとかそういう話?

77 :NAME IS NULL:2015/12/28(月) 16:05:32.61 ID:???.net
Transact-SQL 使っても良いんじゃない?

78 :NAME IS NULL:2015/12/28(月) 17:11:36.25 ID:???.net
UPDATEとINSERTの2文を1トランザクションで流せば良いだけの気が

79 :NAME IS NULL:2015/12/28(月) 20:45:47.24 ID:???.net
MERGE ぐらいでメンテナンスが難しくになるかなぁ…

80 :NAME IS NULL:2015/12/28(月) 20:53:03.73 ID:FOWa2ASA.net
SQLのテストをしない低レベルなら、かまわないが。

81 :NAME IS NULL:2015/12/28(月) 22:02:22.65 ID:???.net
>>73
できました
ありがとうございます

82 :NAME IS NULL:2015/12/29(火) 03:44:58.15 ID:???.net
>>72
スレチですよ

83 :NAME IS NULL:2015/12/29(火) 12:38:55.09 ID:PogCLmH3.net
SQLを何だと思ってるのかw

まさかStructureなんたらとか思ってるんじゃないだろうなw

84 :NAME IS NULL:2016/01/09(土) 11:31:38.67 ID:???.net
初学者です。
ご回答よろしくお願いします。
単一の表から複数の異なる集約結果を求めたいのですが、以下のような方法しか思いつきませんでした。
なにかもっとスマートな方法はありませんか?

select
(select count(番号) from 在庫) as 合計,
(select count(番号) from 在庫 where 分類='メンズ') as メンズ計,
(select count(番号) from 在庫 where 分類='レディース') as レディース計,
(select count(番号) from 在庫 where 分類='ジュニア') as ジュニア計

85 :NAME IS NULL:2016/01/09(土) 12:34:33.27 ID:???.net
>>84
>>5

86 :NAME IS NULL:2016/01/09(土) 14:04:40.10 ID:P8kdYMvv.net
>>84
それの方が分かりやすい。

ただなんのために横列で取得したいの?

union allで複数行で取得してもいいと思うけど?

87 :NAME IS NULL:2016/01/09(土) 14:24:07.10 ID:???.net
>>86
ありがとうございます。
これでも変なSQLではないのですね?
union all とかも考えたんですが、上の例で言うと、
アイテム数(行数)が数百万で分類が数十万とかになるので、かえって遅くなるかと思いました。

88 :NAME IS NULL:2016/01/09(土) 14:29:38.09 ID:???.net
かえって遅くなると考えたのはどうして?

89 :NAME IS NULL:2016/01/09(土) 14:52:19.58 ID:???.net
まさかGROUP BY知らないとかじゃないよな
分類でGROUP BYして、必要ならアプリで縦横変換ってパターンじゃないのかねぇ

90 :NAME IS NULL:2016/01/09(土) 22:50:39.07 ID:4FHVsotA.net
>>87
分類が数十万もあるなら、数十万カラムもあるSELECT文を発行するつもりだったのか?

どんな言語で処理したいのか、どんな方法で見たいのか分からないが、プログラムだとしても恐ろしいことになるぞ。

91 :NAME IS NULL:2016/01/09(土) 22:56:36.82 ID:4FHVsotA.net
>>87
データベース内の処理はほぼ同じなので性能差を体感できないだろうよ。

92 :NAME IS NULL:2016/01/09(土) 23:25:13.64 ID:???.net
>>90
ありがとうございます。
本件(に限って)の場合、数十万に及ぶ全ての分類の集計が必要なのではなく、
数十万のうち常に3つの分類(の組み合わせ)の集計だけが必要だったのです。

93 :NAME IS NULL:2016/01/09(土) 23:26:25.39 ID:???.net
アイテム数が数百万と言うのはあると思うけど、
実務で分類が数十万になるケースってあるのかな。
仮にあったとして、そのレベルで集計した物を
どういう風に利用するんだろうか。

94 :NAME IS NULL:2016/01/09(土) 23:32:21.31 ID:???.net
直前の書き込み見て無くてごめん。
その時々で集計したい分類が決まるというなら、
union all の方が柔軟性があるんじゃないかな。

95 :NAME IS NULL:2016/01/10(日) 00:20:26.29 ID:4AZcq86j.net
>>92
検索結果が必ず一貫性の取れた

96 :NAME IS NULL:2016/01/10(日) 00:23:36.54 ID:4AZcq86j.net
>>92
あとそれってある時点の一貫性の取れた検索結果じゃないといけないの?

検索中にデータが増減しないなら、無理に一つのSQLにする必要もない。

97 :NAME IS NULL:2016/01/10(日) 01:18:03.30 ID:???.net
>>96
ありがとうございます、質問者です。
すいません、「一貫性の取れた検索結果」というのはどう言う意味でしょうか?
データベース用語でしょうか?

あと、在庫とかメンズ、レディースというのは便宜上使っただけで、
実際のsubjectはある集団の「人間」です。

98 :NAME IS NULL:2016/01/10(日) 03:17:44.84 ID:4AZcq86j.net
>>97
SELECT文を実行するときに、他のセッションが在庫テーブルにレコードを登録、削除するかどうかということ。

1つのSELECT文で検索すると読み取り一貫性が担保される。

複数のSELECT文で検索すると合計が合わないかもしれない。

99 :NAME IS NULL:2016/01/10(日) 07:13:17.63 ID:???.net
すなおに3回select文発行すれば良いだけの気がするが
整合性うんぬんなら、しかるべき分離レベルの1トランザクションにすれば良いだけ

100 :NAME IS NULL:2016/01/10(日) 07:49:32.48 ID:???.net
ド素人がSQLってどんなものか勉強するのにおすすめな本や方法ってありますか?
あとそういう人が行くべきスレはどこですか?

総レス数 1006
265 KB
新着レスの表示

掲示板に戻る 全部 前100 次100 最新50
read.cgi ver 2014.07.20.01.SC 2014/07/20 D ★