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

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

ただいまの
回答率

90.00%

特定もカラムの最大値を有するレコードを取得する

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,086

SugiuraY

score 244

お世話になります。
現在、以下のテーブルの状況です。

Atable
secid sales
100   200
100   500
200   50
200   100
300   1000


ここでsecidカラムの中で100のgroupに属する最大のsalesのレコードを取得したいです。(つまりsecid:100,
1 sales:500のレコードです)
これについて

$secid=100;
$sql1 = $wpdb->prepare("SELECT * FROM $wpdb->Atable WHERE secid=%d AND
    sales=(SELECT MAX(sales) from Atable)",$secid);

*wordpressの$wpdbクラスを利用していてますが、通常のSQL文やPDOの記法でのご回答でも構いません。
通常のPDOであれば以下のようになりますでしょうか。

$sql1 = prepare("SELECT * FROM Atable WHERE secid=:secid AND
    sales=(SELECT MAX(sales) from Atable));
        stmt->bindValue(':secid',$secid,PDO::PARAM_STR);


https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/wpdb_Class
var_dumpの結果
array (size=0)
  empty


where句でsecidとmax条件を絞るような方法はダメなのでしょうか?
いろいろ調べたのですが、うまくいかなかったため、ご質問させていただきました。

よろしくお願い申し上げます。


以下、追加の状況
A.ichi様にご教示頂いた方法で、データを取得することができたのですが、幾つかのカラムについて
想定していないデータを持ってきてしまいます。
実際のコードとテーブルの方がご理解いただきやすいと思いましたので
いかに記載します。

quote.phpで取得した配列の結果の結果をごらんください
'xki' => string '28' (length=2)
'fisperiod' => string '2015年6月期' (length=14)

について、table $wpdb->zaimumasterの配列(テーブル)にある通り
本来はMAX値の201606のレコードであれば
'xki' => string '30' (length=2)
'fisperiod' => string '2016年6月期' (length=14)
を持ってこなければならないのに、intperiodが
201512のMIN値のものを持ってきます。
重ねてで申し訳ございませんが、よろしくお願い申し上げます。

quote.php
$sql1 = $wpdb->prepare("SELECT*FROM $wpdb->zaimumaster t1 JOIN (SELECT secid,xki,fisperiod,max(intperiod) intperiod
                                        FROM $wpdb->zaimumaster GROUP BY secid) t2 using(secid,intperiod) where t1.secid=%d",$secid);
                                      $rows1 = $wpdb->get_results(($sql1), ARRAY_A);
                                        var_dump($rows1);
quote.phpで取得した配列の結果

array (size=1)
  0 => 
    array (size=25)
      'secid' => string 'ZZZZ' (length=4)
      'intperiod' => string '201606' (length=6)
      'id' => string '3' (length=1)
      'name' => null
      'xki' => string '28' (length=2)
      'period' => string '前期' (length=6)
      'fisperiod' => string '2015年6月期' (length=14)

ここに言語を入力
table $wpdb->zaimumaster

array (size=3)
0 => 
array (size=25)
'id' => string '1' (length=1)
'name' => null
'xki' => string '28' (length=2)
'secid' => string 'ZZZZ' (length=4)
'period' => string '3期前' (length=7)
'fisperiod' => string '2015年6月期' (length=14)
'intperiod' => string '201506' (length=6)
1 => 
array (size=25)
'id' => string '2' (length=1)
'name' => null
'xki' => string '29' (length=2)
'secid' => string 'ZZZZ' (length=4)
'period' => string '2期前' (length=7)
'fisperiod' => string '2015年12月期' (length=15)
'intperiod' => string '201512' (length=6)

2 => 
array (size=25)
'id' => string '3' (length=1)
'name' => null
'xki' => string '30' (length=2)
'secid' => string 'ZZZZ' (length=4)
'period' => string '前期' (length=6)
'fisperiod' => string '2016年6月期' (length=14)
'intperiod' => string '201606' (length=6)
```

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • timy

    2016/10/15 17:11

    例だと最大salesは500なのでは? intperiod というカラムは何? 「ダメなのでしょうか?」とありますが上記のコードを実行した結果はどうなっていますか?

    キャンセル

  • SugiuraY

    2016/10/15 17:18

    timyさま コメントありがとうございます。ご指摘の通り修正いたしました。SQLからはエラーが吐き出されず、var_dumpの結果は空です。。その旨も加筆いたしました。

    キャンセル

  • A.Ichi

    2016/10/15 19:07

    余分と思われる部分を削除いたしました。

    キャンセル

回答 1

checkベストアンサー

0

sqlの部分だけです、ご参考まで

$secid=100;
$stmt = $wpdb->prepare("select t1.* from Atable t1 join (select secid, max(sales) sales from Atable group by secid) t2 using(secid,sales) where t1.secid=:secid");
$stmt->bindValue(':secid',$secid));
$status = $stmt->execute();
if (!$status) {
   $err = $stmt->errorInfo();
}
$rec=$stmt->fetch(PDO::FETCH_ASSOC);
print_r ($rec);

上記の例題を見て修正してみました

$sql1 = $wpdb->prepare("
SELECT * FROM $wpdb->zaimumaster t4 JOIN
(SELECT id,xki,secid FROM $wpdb->zaimumaster t1
 JOIN (SELECT secid, max(intperiod) intperiod FROM $wpdb->zaimumaster) t2
 USING( secid,intperiod ) WHERE secid=%d
) t3 USING (id,xki,secid);
",$secid);

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/10/15 20:52

    ありがとうございます、勉強をさせていただきます。

    キャンセル

  • 2016/10/15 21:16

    簡単ですがお答えを書きました。
    ご質問(1)
    t1.* はJOINするテーブルのどちらかのテーブルの全項目を示しています。t1 join t2のときに明示的にテーブルを指定しました。
    t


    ご質問(2)
    max(intperiod) intperiodは、正しく書くとmax(intperiod) AS intperiod です。手抜きですみません。
    サブクエリはメモリ上に仮に作成されるテーブルと思って頂いてよいと思います。よくインデックスが
    利かないので遅くなる原因となるものです。

    ご質問(3)
    サブクエリの結果とJOINして一致するものを抽出しています。比較するusingは項目名が同じ場合に使います。
    ON の場合 t1.aaa = t2.aaa and t1.bbb = t2.bbb と書きます。比較項目名が異なる場合はONです。

    キャンセル

  • 2016/10/16 08:10

    お手数をおかけして、申し訳ございません。かなりクリアになりました。
    改めてお力添えに感謝を申し上げます。
    宜しくお願い申し上げます。

    キャンセル

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

  • ただいまの回答率 90.00%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる