• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:複雑なorder by)

複雑なorder byによるスレッド取得方法

このQ&Aのポイント
  • 複雑なorder byを使用して、スレッドを親スレッドごとに取得し、作成日の降順に表示する方法について説明します。
  • 例えば、テーブルがT_BOARD(掲示板テーブル)で、id(スレッドID)、parent_id(親スレッドID)、created(作成日)のカラムで構成されているとします。
  • 現在はselect buid_id,created from T_ROOM where parent_id = 0 order by created;のようなSQLを使用していますが、これだと親スレッドの作成日降順にしか取得できません。

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

  • ベストアンサー
  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.5

条件が以下3つ、すなわち ・子スレッドは必ず親スレッドより新しくなる ・親スレッドに対して子スレッドは複数存在する ・子スレッドに対して子スレッドはない であれば、以下の単純なクエリで必要十分かと SELECT IF(parent_id=0,id,parent_id) AS xid,MAX(created) AS created FROM T_ROOM GROUP BY xid ORDER BY created DESC 汎用性を考えると以下になるかもしれません。 SELECT T1.id,T1.parent_id,COALESCE(MAX(T2.created),T1.created) AS created FROM `T_ROOM` AS T1 LEFT JOIN `T_ROOM` AS T2 ON (T1.id=T2.parent_id) WHERE T1.parent_id=0 GROUP BY T1.id ORDER BY created DESC

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

その他の回答 (4)

  • mitoneko
  • ベストアンサー率58% (469/798)
回答No.4

>実はUserテーブルがあり、user_idをLEFT JOINでさらにUserテーブルをつなげて自分なりにやってみたのですが、うまくいきませんでした…  #2で掲載したSQLは、実際にMySQL5.5.8でテストテーブルを作成して動くのを確認したSQLをそのままコピーした物です。  ちなみに、#3も構文を読んでいる限り、そのままの形で実行できるはずです。  うまくいかなかったなら、どんなSQLを作成して、どう動かなかったのかをちゃんと説明していただかないと、これ以上のアドヴァイスのしようが無いわけです。(「うまくいかない」にも、いろいろあります。構文エラーが出て動かないから、思ったのと違う結果が出るとか、いつまで待っても結果が帰ってこない(要するに遅すぎる)まで多種多様です。)  補足していただく時には、MySQLのバージョンも書いておいた方が良いですよ。MySQLはバージョンが変わると、とたんに出来ることと出来ないことが大幅に変わることがありますから。

rufas
質問者

お礼

すみません。 実際使っているテーブル名を書いてしまいました。(混乱させてしまいすみません) treeboardsはT_ROOMと同じです。 今回追加取得したいテーブルはUsersです。

rufas
質問者

補足

失礼いたしました。 質問の範囲を超えてしまうと思いましたので… そもそも、質問を省略してしまったのがいけなかったですね。 MySqlのヴァージョンはこれですか?コマンドプロンプトの貼り付けです。 Server version: 5.0.83-community-nt MySQL Community Edition (GPL) Userテーブルを自分なりにつなげてみましたが、 順番がうまくとれませんでした。 取得したいフィールドはすべてになります。 select * from treeboards AS Treeboard LEFT JOIN users AS User on (Treeboard.user_id = User.id) where Treeboard.id IN( SELECT Treeboard.id FROM treeboards AS Treeboard LEFT JOIN treeboards AS T2 ON (Treeboard.id=T2.parent_id) OR (Treeboard.id=T2.id) WHERE Treeboard.parent_id=0 and Treeboard.del_flg = 0 GROUP BY Treeboard.id ORDER BY MAX(T2.created) DESC)

全文を見る
すると、全ての回答が全文表示されます。
  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.3

>5,0 (親スレッド自身が最新) >3,0(id4が2011/5/20) >1,0(id2が2011/4/11) createdに関しては子文書を優先でよいですね? また子文書は複数存在しないということでよいですね? SELECT T1.id,T1.parent_id,COALESCE(T2.created,T1.created) AS created FROM `T_ROOM` AS T1 LEFT JOIN `T_ROOM` AS T2 ON (T1.id=T2.parent_id) WHERE T1.parent_id=0 GROUP BY T1.id ORDER BY created DESC

rufas
質問者

補足

毎度説明不足ですみません。 子スレッドは必ず親スレッドより新しくなりますので、 必然的に子スレッドが優先になります。 親スレッドに対して子スレッドは複数存在します。 ただし、子スレッドに対して子スレッドはありません。 実はUserテーブルがあり、user_idをLEFT JOINでさらにUserテーブルをつなげて自分なりにやってみたのですが、うまくいきませんでした…

全文を見る
すると、全ての回答が全文表示されます。
  • mitoneko
  • ベストアンサー率58% (469/798)
回答No.2

 複雑なorder byと言うよりは、特殊な結合と言うタイトルの話題かな。下手をすると、複雑な特殊な結合になりそうな気がする。  まず、書いてあるデータのパターンだけで動けば良いのなら・・・(細かい突っ込みを入れると、結果の例示、間違ってますけど・・・まぁ、正しいデータに脳内変換して・・・) SELECT p.id, greatest(max(p.created), ifnull(max(c.created),'1800/01/01')) FROM t_room p left outer join t_room c on p.id = c.parent_id WHERE p.parent_id = 0 group by p.id order by greatest(max(p.created), ifnull(max(c.created),'1800/01/01')) desc  とかいう形になるでしょうか。  自分との自己結合で、直系の子スレッドの日付を取ってきて、親スレッドのidでグループ化して、求める作成日をmax関数で取っているわけですが、子スレッドが一つも無い時に、createdがnullを返すと、greatestの結果もnullになってしまうので、ifnullで回避しています。  問題は、このデータに、例えば、   6,4,2011/10/10  なんて一行が入ると、破綻します。つまり、子供の子供ですね。これを扱うには、再帰が必要になりますが・・・  これをちゃんと扱うSQLはちょっと思いつけないです。

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

仕様が変じゃない? >5,0 (親スレッド自身が最新) は、まぁいいとして >3,0(id2が2011/5/20) parentが3なのはid4ですよ?? >1,0(id4が2011/4/11) parentが1なのはid2ですよ?? そしてid2のcreatedとid1のcreatedだとid1の方が最新ですよ?? 一体全体どうしたいのでしょうか・・・ 勝手に想像して、こうしてみましたが、命題が間違っているだけになんとも SELECT T1.id,T1.parent_id,MAX(T2.created) AS created FROM `T_ROOM` AS T1 LEFT JOIN `T_ROOM` AS T2 ON (T1.id=T2.parent_id) OR (T1.id=T2.id) WHERE T1.parent_id=0 GROUP BY T1.id ORDER BY created DESC

rufas
質問者

補足

ありがとうございます。 簡潔な例題を提示しようとして、修正を繰り返し、逆におかしなことになっていました。 ご指摘の通りの間違いでした。 問題の意図を理解していただいてよかったです。 書き直してみました。 5,0 (親スレッド自身が最新) 3,0(id4が2011/5/20) 1,0(id2が2011/4/11)

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

関連するQ&A

  • cakephpでスレッド型掲示板

    新人プログラマーです。 今度、cakephp 1.2を使ってスレッド型の掲示板を実装する事になったんですが、どうやって実装していいのか分からず困っています(汗) 他のサイト等を見てもcake等のフレームワークを使ってのスレッド型の掲示板がなどがなく参考にするものがなくお手上げ状態です。 掲示板のテーブルは id title contents parent_id created modifield という感じでparent_idが親子IDという感じになります。 親と子ぐらいまでなら関連付けて取得出来るんですが、孫やそれ以下をどうやって関連付けるのかがよく分かりません。 すみませんが、どなたか教えてください。 宜しくお願いします!

    • 締切済み
    • PHP
  • GROUP BY/ORDER BYの併用で期待するORDERが得られま

    GROUP BY/ORDER BYの併用で期待するORDERが得られません。 データベース初心者です。よろしくお願いいたします。 table id group_id name 1 1 冷蔵庫1 2 2 カメラ1 3 2 カメラ2 4 2 カメラ3 5 3 テレビ1 のようなテーブルを、group_idでグループ化し、idの大きい順に並べた以下のようなデータ id group_id name 5 3 テレビ1 4 2 カメラ3 1 1 冷蔵庫1 を取得しようとして悩んでおります。 SELECT MAX(id) AS max_id, id, group_id, name FROM table GROUP BY group_id ORDER BY max_id DESC というクエリですと max_id id group_id name 5 5 3 テレビ1 4 x 2 y 1 1 1 冷蔵庫1 という結果が得られますが、xとyところが、期待するx=4、y=カメラ3とならないケースがあります。 いくつかのテーブルで試しましたが、期待する結果になるものとならないものがありました。 例えばこれを自己結合することも考えたのですが、WHERE句にASで命名した「max_id」が含まれると「max_idが不明」というエラーが出ます。 MySQLのバージョンは4.0.xでして、サブクエリーが使えません。 このような状況で、何か方法がございましたらご教授のほどお願い申し上げます。 「期待する結果がクエリ1回で得られない」ということを知れるだけでも構いません。 どうぞよろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • 紐づいた個数を取得したい

    以下のようなテーブルがあった場合、PARENT が 0 のものを抜き出して、且つそれに紐づいてるカラムの個数を取得したいのですが、どのようにしたらいいでしょうか? +---+----+--------+ + ID | XXX | PARENT | +---+----+--------+ + 1 | *** | 0 | +---+----+--------+ + 2 | *** | 1 | +---+----+--------+ + 3 | *** | 4 | +---+----+--------+ + 4 | *** | 0 | +---+----+--------+ + 5 | *** | 1 | +---+----+--------+ + 6 | *** | 0 | +---+----+--------+ + 7 | *** | 4 | +---+----+--------+ + 8 | *** | 4 | +---+----+--------+ *PARENT には、ID に紐づいた値が入ります 出力例 +---+----+--------+ + ID | XXX | COUNT | +---+----+--------+ + 1 | *** | 2 | +---+----+--------+ + 4 | *** | 3 | +---+----+--------+

  • group byで最後のレコードを抽出したい

    group byで特定のカラムをまとめる際に、最後(最新)のレコードを抽出したいのですが 最初(古い)の行が抽出されてしまいます。 例えば、threadカラムとuptimeカラムがあるテーブルBBSで threadカラムをgroup byでまとめる際にuptimeの降順(desc)でまとめたい場合 どのようにしたらいいでしょうか? 【テーブルBBS】 id thread uptime 1 1 1230100000 2 2 1230200000 3 1 1230300000 4 3 1230400000 5 1 1230500000 6 2 1230600000 select * form bbs group by thread order by uptime desc だと thread uptime 3 1230400000 1 1230300000 2 1230200000 になってしまいます。 次のような結果を表示するにはどのようにしたらいいでしょうか。 thread uptime 2 1230600000 1 1230500000 3 1230400000 また、DISTINCTを使うと同じフィールド内に重複したレコードがある場合は最初のレコードのみ表示されますが、最後のレコードのみ表示するにはどのようにすればいいのでしょうか? よろしくお願い致します。

    • ベストアンサー
    • MySQL
  • iframe内からjQueryで指定したい

    jQueryのparentで親要素のIDを収得したいのですが、iframe内から、 読み込み元のHTMLを.parent()で追っていくと、取得できません。 jQuery("div#main iframe").contents().find('body').click(function(){ var hoge = jQuery(this).parent().parent().attr("id"); alert(hoge); }); .parent()では読み込み元のHTMLをまでいけないようなんですが、jQueryでは取得できないのでしょうか。 他にiframeから親を取得する記述があるのでしょうか。 アドバイスいただけると助かります。 拙い説明で恐縮ですが、どうぞよろしくお願いします。 こちら↓の板が閉鎖されるのを知らずにポストしていまい、 http://www.tagindex.com/cgi-lib/q4bbs/patio.cgi 解決の見込みがなさそうですで、改めてこちらでお尋ねしています。 ややマルチ気味で恐縮ですが、ご容赦ください。

  • PostgresSQL8.4でツリー上に取得したい

    PostgresSQL8.4でツリー上に取得したい こんにちわ。 PostgresSQLでツリー上にデータを取得したいのですが、思ったように取得できないのでご教授をお願いします画像の「取得したい順番」。 データはid,name,parentとの構造になっています。 データは親子構造になっており、親の下に子が並ぶようにしたいんです。 子は親のidをparentに持っています。 元のデータは画像の「元データ」になっています。 現状再起SQLでデータを取得しid or parentでソートを掛けているのですが、意図した通りに取得できません画像の「取得出来る順番」。 そもそも再起SQLでできるのか、相関サブクエリを使うのか・・・SQLのみでできるのかすら分からなくなってきました・・・。 何か画像の「取得したい順番」通りに取得する方法はないでしょうか。 ヒントだけでもいいので、ご教授をお願いします。

  • LEFT JOIN と GROUP BY

    こんにちは。 以下の2つのテーブルを結合して、 subcategory_item_idごとのアンケート数を取得したいと思っております。 サブカテゴリー項目テーブル subcategory_item_id category_id subcategory_id subcategory_item_name content image_url アンケート詳細テーブル enquete_detail_id enquete_id store_id category_id subcategory_id subcategory_item_id 試しに作成した以下のSQL文でMySQLで実行したところ、アンケート詳細テーブルにsubcategory_item_idが含まれていない場合も件数0のレコードとして取得したいのですが、うまく取得できませんでした。 select sci.subcategory_item_id, sci.subcategory_item_name, count(ed.enquete_detail_id) c from subcategory_item sci left join enquete_detail ed on (ed.subcategory_item_id = sci.subcategory_item_id) group by ed.subcategory_item_id お手数をおかけしますが、ご教授いただけると助かります。 よろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • 2回SELECTせずにすむ方法?

    <やりたいこと> ・(ブログの)エントリーデータを元に、「categoryテーブル」より、親カテゴリー内容と、子カテゴリー内容を抽出したい <テーブル構成> ■categoryテーブル ・category_idカラム ・parent_idカラム ・その他色々カラム <現状> 1. SELECT * FROM category where category_id = :category_id 2. 1で抽出したデータのparent_idを取り出して、再度、SELECT   SELECT * FROM category where category_id = :parent_id <質問> ・2回SELECTしているのが冗長な気もするのですが、普通はどう書くのでしょうか? ・もっと良いテーブル構成があれば教えてください ※内容 … ブログの「メイン」「サブ」カテゴリー。1つのメインカテゴリーにつき、サブカテゴリーが複数

    • ベストアンサー
    • MySQL
  • 複雑なSQL文について

    SQLite バージョン3.7.10 を使用しています。 以下のサイトにソースがあります。 http://ideone.com/7FPtHL どう説明するのが適切なのかあまり分かりませんが、 よろしくお願い致します。 t5テーブルにおいて t2テーブルのt1_key1が't1_key_1' かつ t5テーブルのt3_keyに対応するt3テーブルのt1_keyに対応するt2テーブルのt1_key2の 例えば2012年1月の (t5テーブルのprofit × その日(t5テーブルのdateの日の部分)に対応した2テーブルのrate) を t4テーブルのkeyごとにグループ化してその合計値を高い順に出力したいのですが、 のですがどのようなSQL文を書けば良いのでしょうか? ※ ただし、もしt5テーブルのdateに対応する日付がt2テーブルのdateにない場合は、 t5テーブルのdateに対応する月(年も含めて)のt2テーブルのrateの平均値、 それもない場合は、t5テーブルのdateに対応する年のt2テーブルのrateの平均値、 それもない場合は、t5テーブルの全てのrateの平均値、 を取得してt5テーブルのprofitにかけたいのです。。 ※ 例えばこのデータなら 2012年1月は +----------+------+ | t4_name  | sum | +----------+------+ | t4_name_1 |500000| +----------+------+ | t4_name_2 |150000| +----------+------+ という結果が得たいです。 t5テーブルのdateの'2012-01-03 00:00:02'の日付に対応するt2テーブルのdateは存在しないので、 t2テーブルの1月(2012-01)のrateの平均値((100+200+300)/3=200)を profitにかけています。 複雑すぎるというか自分でもうまく説明できないので、 せめて※の部分のSQLの書き方だけでもアドバイス頂けないでしょうか?

  • 親子関係があるテーブル内での検索

    親のidを保持するテーブルです。 CREATE TABLE `tbl` ( `id` int PRIMARY KEY, `parent_id` int, FOREIGN KEY(`parent_id`) REFERENCES `tbl`(`id`) ) ENGINE=InnoDB; このテーブルで「parent_idがNULLで、かつ、子を持たない(親というか子でもないというか)行」 を検索したいのですが、どのようなSQLを記述すれば良いのでしょうか?

    • ベストアンサー
    • MySQL