以下の2テーブルの構成で、from_uid毎のto_uidへの在庫移動個数(val)を集計したいと考えています。
ユーザテーブル(user):uid(int), name(string)
在庫移動管理テーブル(zaiko):id(int), from_uid(int), to_uid(int), val(int)
たとえば、それぞれ以下のようなレコードがあった場合、
<user>
uid, name
1 aaa
2 bbb
3 ccc
<zaiko>
id, from_uid, to_uid, val
1 1 2 3
2 1 2 5
3 2 1 1
4 3 1 4
結果として、以下を得たいと考えています。
uid=1で検索した場合
to_uid, val
1 0
2 7
3 -4
uid=2で検索した場合
1 -7
2 0
3 0
uid=3で検索した場合
1 4
2 0
3 0
(イメージとしては、対戦表?の以下のような表を一行ずつ取得する様な感じです。)
___1__2__3
1__0__7_-4
2_-7__0__0
3__4__0__0
上記のような結果を得たい場合、どのようなSQLを書けばよいのでしょうか。
内容について、わかりづらい点等がありましたらご指摘ください。
A 回答 (5件)
- 最新から表示
- 回答順に表示
No.5
- 回答日時:
#2の補足です。
対戦表風に横に並べたいのなら、下記の様に並べてSELECT句にサブクエリを並べて書けばよいです。SELECT
uid,
COALESCE((SELECT SUM(val) FROM zaiko WHERE from_uid = 1 AND to_uid = uid), 0) -
COALESCE((SELECT SUM(val) FROM zaiko WHERE to_uid = 1 AND from_uid = uid), 0) AS from_1,
COALESCE((SELECT SUM(val) FROM zaiko WHERE from_uid = 2 AND to_uid = uid), 0) -
COALESCE((SELECT SUM(val) FROM zaiko WHERE to_uid = 2 AND from_uid = uid), 0) AS from_2,
COALESCE((SELECT SUM(val) FROM zaiko WHERE from_uid = 3 AND to_uid = uid), 0) -
COALESCE((SELECT SUM(val) FROM zaiko WHERE to_uid = 3 AND from_uid = uid), 0) AS from_3
FROM user
ORDER BY uid;
(縦横を入替えるには引き算の前と後を入替えます)
また、#4さんのSQLは MySQL version 5.5.8 で問題無く動作しました。
下記の様にスカラサブクエリを使っても書けますね。
SELECT
u1.uid AS from_uid,
u2.uid AS to_uid,
COALESCE((SELECT SUM(val) FROM zaiko WHERE from_uid = u1.uid AND to_uid = u2.uid), 0) -
COALESCE((SELECT SUM(val) FROM zaiko WHERE to_uid = u1.uid AND from_uid = u2.uid), 0) AS val
FROM user u1 INNER JOIN user u2
ORDER BY u1.uid, u2.uid;
No.4
- 回答日時:
from,toの全パターンを取得するバージョンです。
件数が多くなるときついと思いますが・・。
SELECT
users.from_uid
,users.to_uid
,COALESCE(SUM(CASE WHEN users.from_uid = zaiko.from_uid THEN val ELSE (val * -1) END), 0) AS val
FROM
(
SELECT u1.uid AS from_uid, u2.uid AS to_uid
FROM user u1
CROSS JOIN user u2
) AS users
LEFT JOIN zaiko ON
(
(users.from_uid = zaiko.from_uid AND users.to_uid = zaiko.to_uid)
OR
(users.from_uid = zaiko.to_uid AND users.to_uid = zaiko.from_uid)
)
GROUP BY users.from_uid, users.to_uid
ORDER BY from_uid, to_uid
;
MySQLの環境が無いので、動作確認はできていません。
No.3
- 回答日時:
この手の集計が前提であれば、fromとtoをひっくり返したデータを入れ込んでおくと
ぐっと集計が楽になります
create table user(uid int, name varchar(20));
insert into user values(1,'aaa'),(2,'bbb'),(3,'ccc');
create table zaiko (id int,type int, from_uid int, to_uid int, val int);
insert into zaiko values(1,1,1,2,3),(2,1,1,2,5),(3,1,2,1,1),(4,1,3,1,4);
insert into zaiko values(1,2,2,1,-3),(2,2,2,1,-5),(3,2,1,2,-1),(4,2,1,3,-4);
※表裏を明確にするためtypeカラムをつけておきましたが実質プラスマイナスだけでも
判断はできます。
これを前提に
select from_uid,to_uid,sum(val) as sumvalfrom zaiko group by from_uid,to_uid;
とすれば、いかが得られます
from_uid to_uid sumval
1 2 7
1 3 -4
2 1 -7
3 1 4
これをuserテーブルとリンクさせると表が簡単につくれます
select uid
,sum((to_uid=1)*sub.sumval) as 1
,sum((to_uid=2)*sub.sumval) as 2
,sum((to_uid=3)*sub.sumval) as 3
from user
left join(select from_uid ,to_uid ,sum(val) as sumval from zaiko group by from_uid,to_uid) sub
on user.uid=sub.from_uid
group by uid
No.2
- 回答日時:
スカラサブクエリを使って、全ユーザに対して在庫の出入りの合計を求めれば良いでしょう。
対象のuidを指定するのが2箇所になってちょっと冗長ですが、下記の様な感じになるかと。
uid=1 の場合 -----------------------------
SELECT
uid,
COALESCE((SELECT SUM(val) FROM zaiko WHERE from_uid = 1 AND to_uid = uid), 0) -
COALESCE((SELECT SUM(val) FROM zaiko WHERE to_uid = 1 AND from_uid = uid), 0)
FROM user
ORDER BY uid;
uid=2 の場合 -----------------------------
SELECT
uid,
COALESCE((SELECT SUM(val) FROM zaiko WHERE from_uid = 2 AND to_uid = uid), 0) -
COALESCE((SELECT SUM(val) FROM zaiko WHERE to_uid = 2 AND from_uid = uid), 0)
FROM user
ORDER BY uid;
※ MySQL version 5.5.8 で確認
参考URL:http://gihyo.jp/dev/serial/01/sql_academy2/000402
No.1
- 回答日時:
uid=1で検索した場合
to_uid, val
1 0
uid=2で検索した場合
2 0
・・・
は必ず0のはずですが、それも出したいということですね。
ならば、まず、to_uidを出すためのSQLを考えます。
select distinct to_uid from <zaiko>
で求まりますね。
後は単純に、
select to_uid,sum(val from
(select to_uid, val from <zaiko> where from_uid = 1
union all
select to_uid,0 as val from (select distinct to_uid from <zaiko>)
)
group by to_uid
order by to_uid
で、
uid=1で検索した場合
が求まります。
2・・・も同様。
というのは大嘘で、新たにユーザテーブルに登録されて、from_uidはあれどもto_uidはない場合
漏れます。
select to_uid,sum(val) from
(select to_uid, val from <zaiko> where from_uid = 1
union all
select uid,0 as val from <user>
)
group by to_uid
order by to_uid
のほうが正しいと思われます。
(ただし、to_uidにないuidはto_uidのほうには出したくないなら最初のほうを使ってください)
次に、uid=1,2,3・・・を横に並べる以下のような結果を求めるのは、難しいです。
___1__2__3
1__0__7_-4
2_-7__0__0
3__4__0__0
uidに増減がない(または、増減に対してSQLを修正するつもりがあるならば)のならば、
select to_uid,sum(val1),sum(val2),sum(val3),・・・ from
(select to_uid, val as val1,0 as val2,0 as val3,・・・ from <zaiko>
where from_uid = 1
union all
select to_uid, 0 as val1,val as val2,0 as val3,・・・ from <zaiko>
where from_uid = 2
union all
select to_uid, 0 as val1,0 as val2,val as val3,・・・ from <zaiko>
where from_uid = 3
・・・
union all
select uid,0 as val from <user>
)
group by to_uid
order by to_uid
で求めることができますが、通常はプログラム作って対応するほうが簡明かつ柔軟性に富んでいます。
(というよりユーザテーブルの追加・削除でSQLを変えるというはお薦めしません。)
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- MySQL ある時間以内の利用者の抽出について 3 2022/03/26 11:15
- オンラインゲーム 原神のフレンド申請について 原神を友達とやりたくてフレンド申請を送ろうとしましたが、フレンド検索画面 2 2023/06/13 19:17
- C言語・C++・C# C++のcinの動作 5 2023/02/26 00:13
- PHP php テーブルが作成できない 1 2022/11/17 23:41
- MySQL php テーブルを作れない 2 2022/11/17 18:22
- Oracle sqlで質問です。 aテーブルとbテーブルがあり、下記のsqlで取得したidとnameに一致しないレ 1 2022/04/20 20:34
- PHP クエリObjectをforeachで回す時に、次のレコードへ移動せずに次のレコードを取得したい 2 2022/07/28 15:29
- SQL Server ACCESSで表が作りたく、そのためのSQL文や設定方法を教えてください。 1 2022/08/15 12:28
- Visual Basic(VBA) ExcelからAccessのテーブルに書き込む時に時間がかかる 1 2022/10/14 20:38
- Excel(エクセル) PHPプログラムをエクセルに張り付けると検索ボックスがでてくる! 3 2022/05/08 07:10
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
select文の実行結果に空白行を...
-
割合(パーセント)を求めるには?
-
SQLで連続したカラムが何個ある...
-
SQL文の入れ子について
-
テーブルの最後(最新)のレコー...
-
SQLローダーCSV取込で、囲み文...
-
【PL/SQL】FROM区に変数を使う方法
-
where句中のtrim関数について
-
複数のテーブルから値を合計出...
-
レコードの登録順がおかしい
-
「数字で始まらない」ものを抽...
-
SQL*Loader Append
-
group byの並び順を変えるだけ...
-
count関数の値をwhere句で使用...
-
SELECTした合計値をそのまま割...
-
固定長データのテキストファイ...
-
トランザクションログを出力せ...
-
int型フィールドにnullを登録で...
-
並べ替えについて
-
2つの列が同じ値の行を取得するSQL
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
select文の実行結果に空白行を...
-
割合(パーセント)を求めるには?
-
SQL文の入れ子について
-
空きのID番号を取得する方法
-
SQLで連続したカラムが何個ある...
-
Mysqlで変数を使ったSELECT文の...
-
直近のデータのリストを取得したい
-
SQLだけでselect結果に定数を加...
-
mysql5でGROUP BYごとにLIMIT??
-
SQLにて順列の抽出
-
任意の上位の集計を取得するには?
-
条件付けで集計したものをUNION...
-
時間帯テーブルから直近空き時...
-
時間帯テーブルから直近空き時...
-
LIMIT句で少なくとも1行は選択...
-
Select文1 マイナス Select文2
-
min について
-
MySQLで合計と小計の計算方法を...
-
高速化のためのインデックスの...
-
GROUP BY句の集計について
おすすめ情報