• 締切済み

SQLで部分的にGROUP BYしたいとき(その2

こんばんわ。 先日こちら(http://okwave.jp/qa/q7666702.html) で質問させていただきましたが、まだ問題があったため、 再度質問させていただきます。 以下のような20カラムある「出納帳」テーブルがあって、 同一日付の金額を集約してしまいたいです。 出納帳 ID 日付   金額 伝票 ・・・(全20カラム) 1 2012/8/20 1000 A01 ・・・ 2 2012/8/20 2000 A02 ・・・ 3 2012/8/21 -1000 B01 ・・・ 4 2012/8/21 -2000 B02 ・・・ 5 2012/8/22 3000 A03 ・・・ 6 2012/8/23 4000 A04 ・・・ 7 2012/8/24 -3000 B03 ・・・ 8 2012/8/24 -4000 B04 ・・・ 9 2012/8/27 5000 A05 ・・・ ↓「日付」で金額集約 ID 日付   金額 伝票 ・・・(全20カラム) 1 2012/8/20 1000 A01 ・・・ 2 2012/8/20 2000 A02 ・・・  2012/8/21 -3000    ・・・(-1000と-2000を集約) 5 2012/8/22 3000 A03 ・・・ 6 2012/8/23 4000 A04 ・・・  2012/8/24 -7000    ・・・(-3000と-4000を集約) 9 2012/8/27 5000 A05 ・・・ と集約キー以外はNULLにしたいのですが、 またまた、 ( SELECT ID, 日付, 金額, 伝票, ・・・ FROM  出納帳 WHERE  金額>=0 UNION ALL SELECT NULL, 日付, SUM(金額), NULL, ・・・ FROM  出納帳 WHERE  金額<0 GROUP BY 日付 ) ORDER BY 日付 とUNIONをする方法しか思いつかなかったのですが、 UNIONせずに端的に表現できるSQLはありますでしょうか?

みんなの回答

  • Siegrune
  • ベストアンサー率35% (316/895)
回答No.2

これって、単に金額が+なら、1行ずつ出力して、 -なら、日付でgroup byして出力したいってこと? SELECT case when 金額>0 then ID else Null end, 日付, sum(金額), case when 金額>0 then 伝票 else Null end, ・・・ FROM  出納帳 group by case when 金額>0 then ID else Null end, 日付, case when 金額>0 then 伝票 else Null end, ・・・ order by 日付,case when 金額>0 then ID else Null end ででるはずですが(未検証ですが。)

全文を見る
すると、全ての回答が全文表示されます。
  • dda167
  • ベストアンサー率76% (55/72)
回答No.1

--端的かどうかはともかく…… SELECT MAX(CASE WHEN 金額 < 0 THEN NULL ELSE ID END) AS ID, 日付, SUM(金額) AS 金額, MAX(CASE WHEN 金額 < 0 THEN NULL ELSE 伝票 END) AS 伝票 FROM 出納帳 GROUP BY 日付, CASE WHEN 金額 < 0 THEN 0 ELSE ID END; --UNION使ったほうが分かりやすくていいかも……

ultra789
質問者

お礼

前回に引き続きご回答ありがとうございます。 なるほど!そうすればUNIONを用いずできますね! ですが、たしかに仰るとおり、SELECT句が複雑だなと感じます。 可読性の意味でメンテが難しいかなとおもいます。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • SQLで部分的にGROUP BYしたいとき

    はじめまして。 SQLで部分的にGROUP BYで集計したいのですが、 どうもしっくりくるSQLがかけません。 多分CASEあたりを使うと綺麗で高速なSQLがかけると思っています。 皆様のお知恵をお借りしたく投稿しました。 具体的には以下のような出納帳データで 出納帳 日付     金額 2012/8/20 1000 2012/8/20 2000 2012/8/21 -1000 2012/8/21 -2000 2012/8/22 3000 2012/8/23 4000 2012/8/24 -3000 2012/8/24 -4000 2012/8/27 5000 ↓集計 日付     金額 2012/8/20 1000 2012/8/20 2000 2012/8/21 -3000(-1000と-2000を集約) 2012/8/22 3000 2012/8/23 4000 2012/8/24 -7000(-3000と-4000を集約) 2012/8/27 5000 というように、マイナスの金額は集約してしまいたいのですが、どのようなSQLが最適でしょうか? とりあえず、UNIONかなと思い、 (SELECT 日付, 金額 FROM 出納帳 WHERE 金額>=0 UNION ALL SELECT 日付, 金額 FROM 出納帳 WHERE 金額<0 GROUP BY 日付 ) ORDER BY 日付 とプラス金額とマイナス金額にわけUNIONしたのですが、 もっと綺麗(高速)にやる方法があるのではないか?と思い投稿いたしました。 なにかヒントございましたら、ご教授ください。 DB環境:Oracle 11g

  • UNION / UNION ALL 時のORDER BY について

    初めて質問させていただきます。 表A(以下,TBL_A) と 表B(以下,TBL_B)があり,表名が 異なるだけでカラムの項目数,データ型は一致していてそれぞれ [TBL_A] SELECT * FROM TBL_A ORDER BY 1, 2 [TBL_B] SELECT * FROM TBL_B ORDER BY 2, 1 を UNION / UNION ALL したいのですが,上記のように ORDER BY が異なっている場合にはどのようにすれば いいのでしょうか? 苦戦中の成果物としてはそれぞれに固有の区分カラムを設け, その区分で判断し DECODE で ORDER BY しようとしたのですが 「"右カッコがありません"」と出て行き詰っています。 SELECT 区分, ○○, □□ FROM TBL_A WHERE ○○ = ??? UNION ALL (SELECT 区分, ○○, □□ FROM TBL_B) ORDER BY 区分, DECODE(区分,A,(1,2),B,(2,1)) 宜しくお願いします。

  • group by句

    色々と試行錯誤してやっていますが、なかなか自分の 思うような結果が得られないためご質問させて下さい。 テーブルが全部で3つあります。 テーブルA id name 1 巨人 2   西武 テーブルB id name 1 小笠原 2 ラミレス 3 中島 4  片岡 テーブルC id テーブルAID テーブルBID 背番号 1 1 1 30 2 1 2 10 3 2 3 3 4 2 4 8 テーブルを結合し、テーブルCにある 背番号をテーブルAid,テーブルBidを元に sumしたいのですがうまくいきません。 以下がそのSQLになります。 (1)サブクエリーを使ったSQL この場合値が重複されて表示されてしまいます。 select a.name,b.name,c.name, (select sum(背番号) from tableC c where c.テーブルAId = a.id group by c.テーブルAid ), (select sum(背番号) from tableC c where c.テーブルBid = bid group by c.テーブルBid ) from tableC c inner join tableA a on a.id = c.テーブルAid inner join tableB b on b.id = c.テーブルBid (2) select a.name,b.name,c.name, (select sum(背番号) from tableC c where c.テーブルAId = a.id ), (select sum(背番号) from tableC c where c.テーブルBid = bid ) from tableC c inner join tableA a on a.id = c.テーブルAid inner join tableB b on b.id = c.テーブルBid group by c.テーブルAid 重複はされないのですが、group byが一つのみなので ちゃんとした出力がされません。    他にやり方があるのかもしれませんが、お分かりになる方が    いらっしゃいましたら、ご教授お願い致します。

  • DB2で UNION ALL と GROUP BY の合わせ技のSQLの作り方

    DB2で下記SQLにグループ化して 合計やカウント数を出したいのですが、 うまくいきません --------------------------------------- SELECT A.NYU1 AS NYU ,0 AS SYU ,A.KEN1 AS KEN ,A.CODE1 AS CD From A ) UNION ALL ( SELECT 0 AS NYU ,B.SYU2 AS SYU ,B.KEN2 AS KEN ,B.CODE2 AS CD From B ) ORDER BY CD --------------------------------------- MS-ACCESSなら以下のような感じでうまくいくのですが。。。 SELECT SUM(NYU) AS A ,COUNT(SYU) AS B FROM ( SELECT F1 ,F2 FROM A UNION ALL SELECT G1,G2 FROM B ) GROUP BY NYU ご教授お願いします

  • group by のソート

    mysql Client API version 3.23.49 PHP/4.4.5 で動作させようと思っています。 table a   b 1   2 3   4 2   4 7   1 2   6 1   6 上のデータから以下のような結果を得たいのですが table a   b  idcount1 1   6    2 3   4    1 2   6    2 7   1    1 グループで集計をとり、その上でbに6がある場合は6その他は bの値にNULLもしくは別の値が入るという形でいいのですが・・・ できません。 SELECT a, b, count( * ) AS idcount1 FROM table GROUP BY a するとはじめに読みこんだ値がbには入ってしまいます。 結果 table a   b  idcount1 1   2    2 3   4    1 2   4    2 7   1    1 SELECT a, b, count( * ) AS idcount1 FROM table where b=6 GROUP BY a するとbの値ははじきますし、カウントしている意味がなくなります。 結果 table a   b  idcount1 1   6    1 2   6    1 GROUP BY 処理前のソートを考え、from table後に oder by b=6 asc を使ったがエラー 末尾に oder by b=6 asc を使うと最初に試した値をソートするだけでした。 宜しくお願いいたします。

    • ベストアンサー
    • MySQL
  • 【SQL】group byについて

    SELECT A.商品名 B.商品名 FORM A,B WHERE ((A.店コード IN (引数.店コード)) and (A.商品コード IN(引数.商品コード)) AND (A.店コード = C.店コード) AND ((A.商品コード = D.商品コード) AND (A.店コード = D.店コード)) というSQLに下記条件を追加したいのですが、集計関数の使用方法がわかりません。 SELECT Sum(金額) FROM Q WHERE Q.店コード = A.店コード AND Q.商品コード = A.商品コード GROUP BY Q.店コード, Q.商品コード Qテーブルは 店コード、商品コード、メニューコード がKEYなのですが、 店コードと商品コードだけで集計した値をSELECTしたいのです。 恐れ入りますが、ご教授頂けますよう宜しくお願いします。

  • 同じ構成のテーブルの条件付き結合

    同じ構成のテーブルがテーブル1~テーブル6まであり、6つのテーブルを集計するSQLを作成しています。 カラムは ID、名前、日付1、日付2、ステータス1、ステータス2 です。 IDがプライマリーキーになっており、テーブル1にしかないIDや全てのテーブルに登録されているIDなどもあり、IDの一覧を作成したいです。 IDが重複していた場合、名前はどれを残しても構わないのですが(どのテーブルか指定する必要があるのならばとりあえずテーブル番号が若い方の名前を残すようにしてください。) 日付1は最古の日付 日付2は最新の日付 ステータスは共に優先順位が1>2>0>nullとなっており優先順位が高いほうを残すようにし、ステータスが両方nullの場合は集計しないようにしたいです。 テーブル1 ID、名前、日付1、日付2、ステータス1、ステータス2 111、あああ、2001/1/1、2001/1/1、2、2 222、いいい、2001/1/1、2001/1/1、2、2 333、ううう、2001/1/1、2001/1/1、null、null 555、おおお、2001/1/1、2001/1/1、2、2 テーブル2 ID、名前、日付1、日付2、ステータス1、ステータス2 111、aaa、2002/2/2、2002/2/2、0、null 222、iii、2002/2/2、2002/2/2、1、0 333、uuu、2002/2/2、2002/2/2、null、null 444、eee、2002/2/2、2002/2/2、1、1 結果 ID、名前、日付1、日付2、ステータス1、ステータス2 111、あああ、2001/1/1、2002/2/2、2、2 222、いいい、2001/1/1、2002/2/2、1、2 444、eee、2002/2/2、2002/2/2、1、1 555、おおお、2001/1/1、2001/1/1、2、2 このようなことを6つのテーブルを集計して行いたいです。 SELECT t1.id,MIN(t1.日付1)as 日付1,MAX(t1.日付2)as 日付2,CASE When t1.ステータス1="1" then "1" else t1.ステータス1 end ,CASE When t1.ステータス2="1" then "1" else t1.ステータス2 end FROM( SELECT * FROM テーブル1 UNION All SELECT * FROM テーブル2 UNION All SELECT * FROM テーブル3 UNION All SELECT * FROM テーブル4 UNION All SELECT * FROM テーブル5 UNION All SELECT * FROM テーブル6 )as t1 WHERE NOT(t1.ステータス1 IS null AND t1.ステータス2 IS null) GROUP BY id 日付は出来ていると思うのですが、ステータスで1の優先がまだ出来ていないので修正お願いいたします。

    • ベストアンサー
    • MySQL
  • グループ中で最大値を含む行を抽出するSQLはどう書けば良いでしょうか

    列A,Bでグループ化し、グループ中で列Cが最大値の列を取得したいのです。 数百万件あるので極力低コストにしたく、 副問合せはINDEXが効かないと聞いたのですが、 それ以外思いつきませんでした。 副問合せしない方法はないでしょうか? また、副問合せの中でコストの低いSQLはどんなものでしょうか。 ■テーブルです 名前 型 CUST_ID CHAR(8) BRANCH_ID CHAR(4) VALID_DATE DATE MYDATA VARCHAR2(20) CUST_ID BRAN VALID_DA MYDATA 19740704 0000 06-01-01 comment0001 19740704 0000 05-12-01 comment0000 19740704 0000 06-02-01 comment0002 19740704 0001 06-01-01 comment0011 19740704 0001 06-03-01 comment0012 ■このような結果が欲しいのですが。。。 CUST_ID BRAN VALID_DA MYDATA 19740704 0000 06-02-01 comment0002 19740704 0001 06-03-01 comment0012 ■考えたSQLです(検証済) select a.cust_id,a.branch_id,a.valid_date,a.mydata from test a,(select cust_id,branch_id,max(valid_date) as mvd from test group by cust_id,branch_id) b where a.cust_id=b.cust_id and a.branch_id=b.branch_id and a.valid_date=b.mvd ; select a.cust_id,a.branch_id,a.valid_date,a.mydata from test a where not exists (select * from test b where a.cust_id=b.cust_id and a.branch_id < b.branch_id) ; select cust_id,branch_id,valid_date,mydata from test where (cust_id,branch_id,valid_date) in (select cust_id,branch_id,max(valid_date) from test group by cust_id,branch_id) ; select cust_id,branch_id,valid_date,mydata from (select cust_id,branch_id,valid_date,mydata,max(valid_date) over(partition by cust_id,branch_id) as mvd from test) where valid_date=mvd ;

  • group byのSQLでインデックスを使いたい

    group byのSQLでインデックスは使えないものなのでしょうか. Using filesortにより,全レコードを読んでしまっています. どなたか解決法を教えてください. mysql> describe xxxxx; +--------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------+--------------+------+-----+---------+----------------+ | aaa_id | bigint(20) | | PRI | NULL | auto_increment | | bbb_id | bigint(20) | | MUL | 0 | | | ccc_id | bigint(20) | | MUL | 0 | | +--------+--------------+------+-----+---------+----------------+ mysql> explain select ccc_id from xxxxx group by ccc_id =2; +----+-------------+-------+-------+---------------+--------+---------+------+------+----------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+--------+---------+------+------+----------------------------------------------+ | 1 | SIMPLE | xxxxx | index | NULL | ccc_id | 8 | NULL | 628 | Using index; Using temporary; Using filesort | +----+-------------+-------+-------+---------------+--------+---------+------+------+----------------------------------------------+

    • ベストアンサー
    • MySQL
  • SQLのcount()とgroup by

    以下のようなテーブルがあったとき、 tbl1 id | score 1 | 100 1 | 200 1 | 300 2 | 200 2 | 100 3 | 300 3 | 400 3 | 500 3 | 600 idでまとめて個数を出すとすると、 SELECT count(*) FROM tbl1 group by id とすれば count(*) 3 2 4 と結果が返ってきますが、この結果にidを足して id | count(*) 1 | 3 2 | 2 3 | 4 というようなSQLはどうやって書けばいいのでしょうか? MySQLでは、 SELECT id, count(*) FROM tbl1 group by id と書けるのですが、これは標準的なSQLではNGなそうなので、気になって質問しました。 よろしくお願いします。

このQ&Aのポイント
  • デスクトップパソコンのセキュリティ対策としてESETを契約しているが、最近はノートパソコンをほとんど使っているため、ESETを移行したい。
  • ESETセキュリティソフトウェアの移行方法についての指導をお願いします。
  • ノートパソコンを購入し、デスクトップパソコンからESETのセキュリティ対策を移行したい方法を教えてください。
回答を見る