副問い合わせとGROUPの組み合わせによるSQLの作成方法

このQ&Aのポイント
  • 副問い合わせとGROUPを組み合わせることで、プロジェクトAの月間勤務状況一覧を取得するためのSQLを作成する方法について相談です。社員情報と勤務情報を結合させて、氏名ごとに月ごとの勤務時間を集計したいのですが、副問い合わせを使用する際に社員を指定する必要があり、GROUPの意味がなくなってしまいます。
  • 現在、STAFF表とLABOR表から一発で情報を取り出せるSQLを作成する方法に苦戦しています。副問い合わせを使用することで、月ごとの勤務情報を取得しようとしているのですが、社員ごとに情報を取得しようとすると、副問い合わせ内で社員を指定する必要があります。そのため、GROUPを使う意味がなくなってしまいます。
  • 質問者はプロジェクトAの月間勤務状況一覧を作成するために、STAFF表とLABOR表から一発で情報を取り出すSQLを作成することに困っています。副問い合わせを使用して月ごとの勤務情報を取得しようとしているのですが、社員ごとに情報を取得しようとすると、副問い合わせ内で社員を指定する必要があります。そのため、GROUPを使う意味がなくなってしまいます。アドバイスをお願いします。
回答を見る
  • ベストアンサー

副問い合わせとGROUPの組み合わせ・・・

プロジェクトA 月間勤務状況一覧 氏名 1月 2月 3月 合計 山田 20 10 10 40 川村 10 10 10 30 大沢 20 20 20 60 上記のような一覧をつくりたいのですが、 STAFF表(社員情報)とLABOR表(勤務情報)からSQL一発で 情報を取り出すためのSQL作成に四苦八苦しています。 人別に情報を取り出すには、GROUPを使えばよいというところまではわかるのですが、 月ごとの情報を取得するために副問い合わせを用いる際に、 人別に情報を取得しようとすると 副問い合わせ文内で社員を指定する必要が出てきてしまいます。 すると社員を纏めて表示するためのGROUPを使う意味がそもそもなくなってしまいます。 以上のような点から、SQLを作る事ができないでおります。 どのように記述すれば宜しいでしょうか?アドバイス頂ければ大変助かります。

  • a-2-m
  • お礼率63% (7/11)

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

試しにSQLを作ってみました。 create table STAFF (ID smallint, 名前 varchar(10)); create table LABOR (ID smallint, 社員ID smallint, 年月日 date, 時間数 smallint, プロジェクトID smallint); insert into STAFF values(101,'川口'); insert into STAFF values(111,'宮本'); insert into STAFF values(123,'中田英'); insert into LABOR(社員ID,年月日,時間数) values(101,'2006-01-05',8); insert into LABOR(社員ID,年月日,時間数) values(101,'2006-02-01',10); insert into LABOR(社員ID,年月日,時間数) values(101,'2006-02-15',5); insert into LABOR(社員ID,年月日,時間数) values(101,'2006-03-01',8); insert into LABOR(社員ID,年月日,時間数) values(101,'2006-03-03',10); insert into LABOR(社員ID,年月日,時間数) values(101,'2006-03-10',12); insert into LABOR(社員ID,年月日,時間数) values(111,'2006-01-10',5); insert into LABOR(社員ID,年月日,時間数) values(111,'2006-01-15',10); insert into LABOR(社員ID,年月日,時間数) values(111,'2006-01-31',5); insert into LABOR(社員ID,年月日,時間数) values(111,'2006-02-10',8); insert into LABOR(社員ID,年月日,時間数) values(111,'2006-02-20',8); insert into LABOR(社員ID,年月日,時間数) values(111,'2006-03-20',10); insert into LABOR(社員ID,年月日,時間数) values(123,'2006-01-20',8); insert into LABOR(社員ID,年月日,時間数) values(123,'2006-01-21',8); insert into LABOR(社員ID,年月日,時間数) values(123,'2006-01-22',8); insert into LABOR(社員ID,年月日,時間数) values(123,'2006-03-03',5); insert into LABOR(社員ID,年月日,時間数) values(123,'2006-03-04',5); insert into LABOR(社員ID,年月日,時間数) values(123,'2006-03-05',5); select x.名前, coalesce(sum(case when date_part('month',年月日)=1 then 時間数 end),0) as 1月, coalesce(sum(case when date_part('month',年月日)=2 then 時間数 end),0) as 2月, coalesce(sum(case when date_part('month',年月日)=3 then 時間数 end),0) as 3月, coalesce(sum(case when date_part('month',年月日) between 1 and 3 then 時間数 end),0) as 合計 from STAFF as x,LABOR as y where x.ID=y.社員ID group by x.名前 order by x.名前 ;

a-2-m
質問者

お礼

chukenkenkou様 ありがとうございました! まったく知らなかったSQLです。 勉強になります。 早速、こちらを参考につくってみます。 *なお「宮本」が何故か「川口」と名寄せされて、一緒に集計されてしまうのですが…。 英語名に変えてみたら、正しく集計されました。    1月 2月 3月 合計 川口  28 31 40 99 中田英 24  0 15 39

a-2-m
質問者

補足

名寄せされてしまう理由は分かりませんでしたが、 STAFFの一意識別子(ID)でGROUPすれば、正しく集計されました。 どうもありがとうございました!

その他の回答 (2)

回答No.2

>2)LABOR表(勤務情報) >ID >社員ID(FK:STAFF.ID) >年月日 >時間数 >プロジェクトID(FK:PROJECT.ID) 「月間勤務状況一覧」で集計しているのは、日数のように見えます。 時間数は無視して、勤務日数でだけ集計できればいいのですか? こういう質問をする場合は、 (1)基の各表の列構成 (2)基の各表に入っているデータ例 (3)得たい検索結果 を示してくれないと、適切な回答ができません。 (3)は、質問で示されています。 (1)は、#1さんへの補足説明で示されました。 (2)は、示せませんか?

a-2-m
質問者

補足

chukenkenkou様、回答有り難うございます&言葉足らずで申し訳ありません。 下記の通り回答させていただきます。 ・「月間勤務状況一覧」で集計しているのは、時間数です。勤務時間数は日によって異なるため、月ごとに時間数を集計します。 ・表に入っているデータは以下の通りです。 1)STAFF表(社員情報) ID:100 名前:山田太郎 2)LABOR表(勤務情報) ID:200 社員ID(FK:STAFF.ID):100 年月日:2006/01/03 時間数:8 プロジェクトID(FK:PROJECT.ID):300 3)PROJECT表(プロジェクト情報) ID:300 プロジェクト名:ヘルスケア事業 以上、他にご不明な点がありましたらご指摘頂ければ幸いです。

  • ipsum11
  • ベストアンサー率21% (55/251)
回答No.1

STAFF表(社員情報)とLABOR表(勤務情報)の構成がわかりません...

a-2-m
質問者

補足

ご指摘有り難うございます&言葉足らずで申し訳ありません。 テーブルの構成ですが大まかに言って下記の通りです: 1)STAFF表(社員情報) ID 名前 2)LABOR表(勤務情報) ID 社員ID(FK:STAFF.ID) 年月日 時間数 プロジェクトID(FK:PROJECT.ID) 3)PROJECT表(プロジェクト情報) ID プロジェクト名 以上の通りです。 もし説明不足等ありましたらご指摘頂ければ幸いです。 宜しくお願い致します。

関連するQ&A

  • GROUP BYと副問い合わせ

    SQLで悩んでいるので質問いたします。 テーブル例 日付 タイプ 個数  0901  1    5 0901  1    3 0901  2    2 0901  2    4 0901  3    1 0901  3    2 0902  1    5 0902  1    3 : : とあります。 このデータを日付毎、タイプ毎に個数を取得したいと考えています。 そこで下記のようにSQLを実行 SELECT 日付、sum(個数)asタイプ別個数、タイプ count(*) as タイプ別レコード数 FROM テーブル名 GROUP BY 日付、タイプ ORDER BY 日付、タイプ 取得できるレコードは下記のようになります。 日付 タイプ別個数 タイプ タイプ別レコード数 0901      8    1     2 0901      6    2     2 0901      3    3     2 : となります。 ここまでは簡単にいけたのですが、 できればタイプ別の個数を日付で1レコードで取得できないかと悩んでいます。 期待している取得レコードは下記です。 日付 タイプ1個数 タイプ2個数 タイプ3個数 レコード数 0901     8      6      3      6 0902 : このようにするためにSELECT部分に副問い合わせをしようとしていますがうまくいきません。 SQLで出来る方法があれば、教えてください。 よろしくお願いします。

  • 副問合せについて

    現在使用しているMySQLではサブクエリーが使えないそうで困っています。 以下の表から、group = 2 に所属している人達の中でもっとも若い人MAX(birthday)の 総ての項目(group name birthday address)を取得したいのですが、 サブクエリーを使わずに取得するには、どの様なSQL文で問い合わせたらいいか教えて頂けないでしょうか、 よろしくお願いします。 group name birthday address 01 Aさん 1971-05-21 東京都 02 Bさん 1981-02-03 神奈川県 01 Cさん 1980-07-26 群馬県 01 Dさん 1976-10-31 埼玉県

  • 副問い合わせ

    人の数が一番多いコードに属する情報を全て取得したいです。 コードに人が何人いるかという部分がわからず、式も頓珍漢な出来になってしまいました。 副問い合わせについても教えていただけるとうれしいです。よろしくお願いします。 SELECT * FROM 表 WHERE コード = (SELECT MAX(コード) FROM 表 )

  • 副問合せの書き方について

    実行したい内容は、『同一ナンバー内で1番IDが低いコードNOが2のタイトルを出す』といった内容になります。 以下のように書いて実行したところ、『EXISTSを使わないサブクエリでは、サブクエリの選択リストには、式を1つだけしか使えません。と表示されました。』自身のSQL文に問題があるかもしれませんが、現状は下記のSQL文となっています。 "SELECT id, code, num, title FROM contents WHERE code=2 AND id IN (SELECT MIN(id), num FROM contents GROUP BY num)" 副問合せで、同一ナンバーで1番IDが低いIDを取得し、取得したIDをもとに タイトルを出そうとしました。 どなたか御指導御願い願えませんでしょうか。 宜しく御願いいたします。

  • SQL GROUP BY

    SQLについてお聞きしたいです。番号カラムの中で最大の数字をもつフィールドと 同じコードを持つデータを、表から全て取得したいと思っているのですが 書き出すとGROUP BYの式が間違っているというエラーが出てしまいます。 SELECT * FROM 表 GROUP BY コード HAVING MAX(番号) = コード どう調べればいいのか分からず四苦八苦しています。どこを直せばよいでしょうか?

  • Accessのレポートで、グループフッターで件数を表示するには?

    Accessで社員DBを作っておりまして、レポートで社員数を表示するのに、手間取っています。 テーブル(T社員一覧)のフィールド内容として、所属、氏名、職種、勤務形態としています。 レポートで社員名簿(1ページで)を出力したいと作成中で、 各所属をグループとして、氏名、職種、勤務形態を表示するようにしています。 フッター部分に、各所属の社員数および勤務形態による内訳を表示したいと思い、 まず、各所属の社員数を表示するため、 =Count([名前]) 勤務形態(正社員かパート)でその内訳を表示するため、 =DCount(" [勤務形態] ","T社員一覧"," [勤務形態] ='正社員'") および =DCount(" [勤務形態] ","T社員一覧"," [勤務形態] ='パート'") というのを作ってみたのですが、どうもうまくいきません。 各所属の社員数は、グループフッター部分に、正確に表示されるのですが、 勤務形態別の社員数は、所属毎にカウントせず、すべての一覧の中からの正社員数、パート数となってしまうのです。 なにかよい方法はありませんでしょうか? ご教授いただければうれしいです。

  • SQL 副問い合わせ EXSIST?

    いつもお世話になってます。独学で情報処理勉強しています。 【専門用語をなるべく使わずに】答えていただける方お願いします。 表が「社員表」と「社員有資格表」の二つしかなくて、 社員表    |社員番号|社員名|所属| 社員有資格表 |社員番号|資格名|登録日| 「資格を複数持つ社員を抽出するSQL」で SELECT DISTINCT 社員番号 FROM 社員有資格表 B1 WHERE EXSISTS (SELECT * FROM 社員有資格表 B2 WHERE B1.社員番号=B2.社員番号 AND B1.資格名<>B2資格名) のB1とかB2はなんですか。

  • 副問い合わせについて

    お世話になります。明日から仕事で使うのですが、下記の構文が よく理解できません。宜しくお願い致します。 SQL Severは経験ありません。 経験はInfomixSql,Access,MySql程度です。 (1)行副問い合わせ(副問い合わせの結果が1行n列で返ってくる) SELECT * FROM t1 WHERE (c4, c2) = (SELECT MAX(c1), 'a' FROM t2); このwhere節の結合条件はどのような感じになるのでしょうか? (2)表副問い合わせ(副問い合わせの結果がm行n列(表)で返ってくる) SELECT * FROM t1 WHERE c4 IN ( SELECT c1 FROM t2 WHERE c4 >= 10 ) ORDER BY c1; 、 SELECT x1.c1, x2.y4 FROM t1 x1, ( SELECT c3, SUM(c4) AS y4 FROM t2 GROUP BY c3) AS x2 WHERE x1.c3 = x2.y4 ORDER BY c1; (1)に同じです。 参考になりそうなサイトでも結構ですので 宜しくお願い致します。

  • 副問い合わせでのNULLの抽出方法

    SQLについての質問です。 副問い合わせを使用したとき、NULLのデータも含めて抽出したいの ですが、どうもうまくいきません。 やりたいことを説明すると、まず以下の構造のテーブルがあります テーブル    コード 金額  -------------- 01  |100   01  |110   02  |090   02  |080   03  |200   04  |100   04  |150   05  |400   09  |350   null |100   null |200   集約後データ コード -------- 01  |<--- 1件目 02  |<--- 2件目 03  |<--- 3件目 04  |<--- 4件目 05  |<--- 5件目 09  |<--- 6件目 null |<--- 7件目 まず、テーブルをコードで集約します。集約された結果のデータで上位○件と いう制御をかけたい為、ROWNUMを使用しています。 ただ、実際にほしいデータは集約する前のデータの為、一度集約とROWNUMを使って 絞りこんだデータを副問い合わせしています。 但し、このときNULLが入ったコードも取得する必要があります。 現在のSQLはこんな感じです。 SELECT コード、SUM(金額) FROM テーブル WHERE コード IN ( SELECT コード FROM テーブル WHERE ROWNUM <= 10 GROUP BY コード ) GROUP BY コード このSQLだと、NULLが省かれてしまうため上位6件までしか抽出できません。 実際、NULLを含んだデータを副問い合わせで取得することは可能でしょうか? データベースはオラクル9iです。 宜しくお願いします。

  • 副問合せ?の書き方

    データの副問合せではまってます。 助言いただければ幸いです。 やりたい事 B_IDを起点に、C表E_IDのNAMEを表示。またB表に紐付くA表とC表のE_IDを比較し、一致する場合○をつける。 A表 A_ID,T_ID,E_ID :(A_IDプライマリキー) B表 B_ID,T_ID :(B_IDプライマリキー) C表 C_ID,B_ID,E_ID :(C_IDプライマリキー) E表 E_ID,NAME :(E_IDプライマリキー) 要件 ・取得したいのは以下の条件のE表のNAME。 ・C表のE_IDでNAMEを取得する。 ・C表とA表をE_IDで比較し、一致する場合NAMEの横に「○」をつける。 ・B表のB_IDを指定し、B表(T_ID)と一致するA表とB表(B_ID)と一致するC表を比較。 上記の実行のために以下のSQLを作成しましたが、副問合せで複数行戻るためエラーが出て、 条件をはずすと結果が思うようにでません。 できればSQL文でやりたいのですが こういう場合はどうすればいいのでしょうか? わかりづらいと思いますがよろしくお願いします。 SELECT E.NAME, IF(C.C_ID = (SELECT W.C_ID FROM C AS W JOIN B AS X ON W.B_ID=X.B_ID JOIN A AS Y ON Y.T_ID=X.T_ID WHERE X.B_ID=B.B_ID AND W.E_ID=Y.E_ID),'○','') FROM A,B,C,E WHERE C.E_ID=E.E_ID AND B.B_ID=1; バージョン:MySQL5.0