質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.47%

  • Java

    14101questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • MySQL

    6010questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQLで、2つのテーブルを横に連結し、日付とidの大きい順に抽出したい。

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 4,850
退会済みユーザー

退会済みユーザー

「SQLで、2つのテーブルを横に連結し、日付とidの大きい順に抽出したい。」

MySQLをJAVAで書いています。

下記のように2つの内容が違うが結合キーを持ったテーブルがあります。
「■6.テーブル抽出後のイメージ」のように、抽出するにはどのようなSQL文を
書けばよいでしょうか?

※前回、自作のSQL文を書いて、同じような質問をしようとしたのですが、
 間違ったSQL文を提示することで、逆に混乱を回答者様へ与えてしまったので、
 今回は、あえて文字で、条件等を書いてみました。

*************

■1.2つの構造の違うテーブルがあります。
      テーブルA
      テーブルB

■2.共通キーは、2つ。
      com_id    // 会社ID
      cus_id     // 顧客ID

■3.最大抽出数は、相互に100件。

■4.抽出優先度は、各テーブルのdatetimeの大きい順、次に、idの大きい順。

■5.テーブルAとテーブルB共、テーブル内の全項目を抽出します。

■6.テーブル抽出後のイメージ
テーブルA                                                       テーブルB
------------------------------------------------------------------------------------------
id   com_id  cus_id  name  datetime  ...            id   com_id  cus_id  address  datetime  ...
6         1          1       鈴木1   2015-08-01 11:..   14        1        1          東京1   2015-08-01 11:..
                                                                        13        2         1         東京2   2015-07-21 22:..
7         1          1      鈴木1   2015-07-15 18:..     9         1         1         東京1   2015-07-15 18:..
5         5          1      鈴木4   2015-07-12 11:..           
4         8          1      鈴木5   2015-07-01 23:..    10        8         1          東京8  2015-07-01 23:..
3         67        2      鈴木5   2015-06-21 10:..    11        67       2          東京67 2015-06-21 10:..
                                                                        12        1         33         東京1  2015-06-18 11:..
2         1          1     鈴木1    2015-06-13 11:..     8        1           1          東京1 2015-06-13 11:..
1         4          4     鈴木4    2015-06-05 12:..  
------------------------------------------------------------------------------------------
 #sqlとは関係ないですが、
   等幅フォントの指定方法がわからなかったので、ブラウザによっては、
   表がキレイに揃ってないこがあります。


■7.上記の様に片方にしかレコードがない場合、
    0 や  null で、レコードが無い方を埋める。

■8.両方に共通であるが、テーブルでの連携と関係ない項目に、
    delete_flag = true/false があるので、trueのレコードのみ抽出対象。

以上です。

難しいでしょうか?
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • hirohiro

    2015/08/24 23:12

    idやdatetimeがテーブルAテーブルB両方にあって値が異なる場合、ソートはどちらを優先するのでしょう?

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2015/08/25 04:49

    テーブルAです。

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2015/09/02 18:52

    難しいですね。自分で再検討します。

    キャンセル

回答 3

+1

■3.最大抽出数は、相互に100件。 
合計で100件でも、100件ずつでも微妙に「相互に」では無いように思いますが、ここでは前者を採用しています。
つまり以下のコードを実行すると最大100件抽出されます。
delete_flag = true/false があるので、trueのレコードのみ抽出対象。 
これって、どちらか片方のdelete_flagがtrueなら採用ですよね?
テーブルAとテーブルBのフラグが共に真でないと駄目な場合は修正が必要です。

datetimeとidは、テーブルAにデータが無い場合のみテーブルBのデータを使ってソートします。
テーブルAにレコードがあってもdatetimeがNULLならテーブルBのdatetimeを採用します。

以上のような条件で良ければ、恐らく次のSQLでいけると思います。

SELECT *
FROM (
  SELECT a.*,b.*
    , COALESCE(a.datetime, b.datetime) AS sort_date
    , COALESCE(a.id, b.id) AS sort_id
  FROM テーブルA a
  LEFT OUTER JOIN テーブルB b ON a.com_id = b.com_id AND a.cus_id = b.cus_id
  WHERE a.delete_flag IS TRUE OR b.delete_flag IS TRUE
  
  UNION
  
  SELECT a.*,b.*
    , COALESCE(a.datetime, b.datetime) AS sort_date
    , COALESCE(a.id, b.id) AS sort_id
  FROM テーブルA a
  RIGHT OUTER JOIN テーブルB b ON a.com_id = b.com_id AND a.cus_id = b.cus_id
  WHERE a.delete_flag IS TRUE OR b.delete_flag IS TRUE
) AS tb
ORDER BY sort_date DESC, sort_id DESC
LIMIT 100
※動作検証してないので、エラーがあるかも知れません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/25 07:55 編集

    PostGreSQLなら「 WHERE a.delete_flag IS TRUE OR b.delete_flag IS TRUE」は外に出してもオプティマイザが両方で実行してくれたように思いますが、mySQLはどうなんでしょう?最後に実行するだけで会ったとしても、レコード数が少なくてメモリ使用量を気にしないなら外に出しても中に置いても同じ結果は得られると思います。

    キャンセル

  • 2015/08/25 09:58

    SQLありがとうございます。大変助かります。
    「どちらか片方のdelete_flagがtrueなら採用」の場合は、tureの方のレコードだけ採用です。
    お手数をおかけいたしました。ありがとうございます。

    キャンセル

  • 2015/08/25 12:35

    > 「どちらか片方のdelete_flagがtrueなら採用」の場合は、tureの方のレコードだけ採用です。
    これは微妙に意味が違いまして。
    AとBをJOINで繋げると。
    tableA.delete_flag = false, tableB.delete_flag = true こういうケースも存在しうると思うのです。
    このレコードは抽出するのか捨てるのか?という話でして、普通に考えると抽出するよね。ということで、書いたSQLでは省かないようにしています。

    キャンセル

  • 2015/08/25 21:23

    delete_flag=trueの方のレコードだけ抽出し、delete_flag=falsの方は、nullや0で埋めて抽出したいです。難しければ、抽出後に、各項目の値を取り出す時に、delete_flagの値でプログラム処理で、nullや0で埋めます。

    キャンセル

  • 2015/08/25 21:27

    [書いたSQLでは省かないようにしています。 ]、補足のコメント有難うございます。この一言で、抽出した物が正しいかの見方が変わるので、とてもたすかります。
    お手数をおかけしました。有難うございます。

    キャンセル

0

MySQLにはFULL OUTER JOINがないので、性能を度外視するのであれば
SELECT 各テーブルのカラム FROM tableA
LEFT OUTER JOIN tableB ON tableA.com_id = tableB.com_id AND tableA.cus_id = tableB.cus_id
WHERE
tableA.delete_flag = 1
AND
tableB.delete_flag = 1
UNION 
SELECT 各テーブルのカラム FROM tableA
RIGHT OUTER JOIN tableB ON tableA.com_id = tableB.com_id AND tableA.cus_id = tableB.cus_id
WHERE
tableA.delete_flag = 1
AND
tableB.delete_flag = 1
のようにUNIONを使うことで対応できます。
ORDER BYはこの段階では使えないので、もう一回SELECTで囲んで
ORDER BYすれば良いと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/24 22:17

    ご回答ありがとうございます。
    select文で、全部を囲むということですか?

    キャンセル

  • 2015/08/24 22:22

    よくわからないですが、このsqlだと、同じsqlをunionしているように、見えます。

    キャンセル

  • 2015/08/25 08:01

    横から失礼します
    上は「LEFT OUTER JOIN」下は「RIGHT OUTER JOIN」なので同じものをUnionしてるわけじゃないですね

    キャンセル

  • 2015/08/25 11:22

    hirohiroさんの仰る通り、LEFT OUTER JOINとRIGHT OUTER JOINで動作が異なります。
    tableAにあって、tableBにない場合でも表示するLEFT OUTER JOINと
    tableAに無くても、tableBにある場合に表示するRIGHT OUTER JOINを組み合わせて
    tableA、tableBを両方表示するようにしているのです。

    前提が100件ということで、これでも良いかなと思いましたが、件数が増えれば性能が低下します。
    その場合は、設計自体から見直しが必要になるでしょう。

    例に表示したSQLのまま、ORDER BYをつけると、後者のSELECT文にのみORDER BYがかかります。
    ですので、一旦select文を外側に書いて、fromに入れてしまえば、ORDER BY句は正常に動作します。
    (hirohiroさんの回答がそうなっています)

    キャンセル

  • 2015/08/25 11:57

    ご説明ありがとうございます。
    つくずく、私の知識の無さ、勉強不足(始めたばかりの初心ではありますが、それにしても非常識すぎますね)、を身に染みて思います。
    ご丁寧なご説明、大変お手数をお掛けいたしました。
    おかげで理解できました。心より、ありがとうございます。

    キャンセル

check解決した方法

-7

皆さま、SQLのご提供やご提案ありがとうございました。
私の未熟でエラーがとれなかったり、処理が遅いなど、どれも実現がむずかしいので、
再度、根本から、見直すことにしました。

大変お手数をおかけしたのにとても心苦しく感じております。
この度は、ご回答ありがとうございました。
お手数をおかけして申し訳ございませんでした。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

関連した質問

  • 解決済

    Rails4 論理削除のgem

    参考サイトをみて論理削除のgem paranoiaを導入しましたが 論理削除できず、そのまま削除されています。 deleted_atは追加され、対象モデルにacts_as_para

  • 解決済

    Postgresqlにて複数テーブルの値を抽出条件に指定する方法

    Postgresqlを使用しています。 基礎は多少学びましたがほぼ素人です。 下記の事項を実現したく色々調べましたがイマイチわからなかったのでご教授下さい。 テーブルA

  • 解決済

    mysql timestampにつきまして

    お世話になります。 (目的) ・MYSQLにINSERTまたはUPDATEしたタイミングで日付を自動でカラムに入力する設定をしたいと考えております。 (現状) ・入力したい

  • 解決済

    SQL全テーブル検索

    データベースの全テーブルから、特定の文字列検索したいのですが、 何かいい方法はありませんか? 例えば、顧客から、 システムに表示されている「首相」という文字を すべて「

  • 解決済

    SQLの自己結合について

    SQLの自己結合について質問です。 上のようなテーブルに対して、次のようなSQLを実行した時、 このような結果を得ることができます。 SQL内のサブク

  • 解決済

    現在時刻の挿入

    仕事でSQLを大量に作って実行させているのですが、「updated_date」というカラムにnow()を挿入した結果、そのカラムには「2147483647」と入っていました。(SQ

  • 解決済

    Access2016:テーブルAとテーブルBのデータを同時に削除したい

    以下のようなフォーム画面があります。 内容/数量/単価/小計/備考はサブフォーム、 他の項目はメインフォームです。 画面一番下の検索欄にワードを入力することで、 メインフ

  • 解決済

    mysqlでパーティションについて

    パーティションを張りたいのですがPARTITIONに指定するカラムってPRIMARYのカラムじゃないといけないのでしょうか。 下記のようなエラーが出たので意味合い的にPRIMARY

同じタグがついた質問を見る

  • Java

    14101questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • MySQL

    6010questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。