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

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

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

1421閲覧

[PHP]配列の中から特定の条件に当てはまるレコードを抽出して処理したい

uthio

総合スコア18

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2019/07/12 02:08

前提・実現したいこと

いつも大変お世話になっております。

DBから引っ張ってきた下記の二次元配列の中から

①statusが4で
②かつkindが重複しているものがあれば、
③updateが古いほう(より過去のもの)のstatusおよびflagだけを0にする

ということをやりたいのですが、
途中から行き詰ってしまって…皆さまのお力添えをいただきたいです。

PHP

1<?php 2$list = Array ( 3 [0] => Array ( [no] => 8 [kind] => 5 [flag] => 1 [status] => 4 [update] => 2014-08-20 ), 4 [1] => Array ( [no] => 15 [kind] => 3 [flag] => 0 [status] => 3 [update] => 2016-12-25 ), 5 [2] => Array ( [no] => 22 [kind] => 6 [flag] => 1 [status] => 4 [update] => 2017-03-01 ), 6 [3] => Array ( [no] => 48 [kind] => 9 [flag] => 1 [status] => 4 [update] => 2018-05-22 ), 7 [4] => Array ( [no] => 52 [kind] => 5 [flag] => 1 [status] => 4 [update] => 2014-03-04 ), 8 [5] => Array ( [no] => 55 [kind] => 23 [flag] => 1 [status] => 4 [update] => 2015-09-28 ), 9 [6] => Array ( [no] => 104 [kind] => 2 [flag] => 0 [status] => 3 [update] => 2018-11-11 ), 10 [7] => Array ( [no] => 107 [kind] => 3 [flag] => 1 [status] => 4 [update] => 2015-04-28 ), 11 [8] => Array ( [no] => 109 [kind] => 1 [flag] => 0 [status] => 3 [update] => 2016-10-15 ), 12 [9] => Array ( [no] => 116 [kind] => 23 [flag] => 1 [status] => 4 [update] => 2018-07-10 ), 13 [10] => Array ( [no] => 131 [kind] => 11 [flag] => 0 [status] => 3 [update] => 2013-01-02 ), 14); 15?>

テーブル定義は以下のようになってます。

SQL

1CREATE TABLE TableName( 2no int(11) unsigned auto_increment, 3kind tinyint(3) unsigned, 4flag tinyint(4), 5status tinyint(4) DEFAULT 0, 6update date, 7primary key (no) 8);

試したこと

まずループでstatusが4のものを抽出して、
そのうえでkindが重複しているものを抽出し、
updateが古いほうのstatusとactiveFlagを書き換える。

という手順がいいかと考えて、下記までは書いたのですが、
【kindが重複しているものをさらに抽出してそのうちupdateが古いほうを】
というのをどうすればいいか、どうにも思い浮かばない状態です。

PHP

1<?php 2 3$sql = "SELECT * from TableName where status='3' OR status='4'"; 4$rs = mysqli_query($link,$sql); 5$count=0; 6while($row = mysqli_fetch_assoc($rs)){ 7 $Array[$count]["no"] = $row["no"]; 8 $Array[$count]["kind"] = $row["kind"]; 9 $Array[$count]["flag"] = $row["flag"]; 10 $Array[$count]["status"] = $row["status"]; 11 $Array[$count]["update"] = $row["update"]; 12 $count++; 13} 14 15foreach ($Array as $val) { 16 if ($val['status'] == '4') { 17 //ここでkindの重複および日付の判定をしたい 18 $val['status'] = 0; 19 $val['activeFlag'] = 0; 20 } 21} 22?>

DBからstatus3と4を取得しているのは他の処理でも3のレコードが必要なためです。
そもそもこの取得を一度にやろうとせず、もうちょっと考えるべきでしょうか。

間違っていたり、もっと効率的な方法がありましたら
ご指摘頂戴できれば大変助かります。

補足情報(FW/ツールのバージョンなど)

所謂レガシーシステムを扱っておりまして、
PHP環境は5.3になります。
array_columnなどが使えない状態です。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2019/07/12 02:12

>DBからstatus3と4を取得しているのは他の処理でも3のレコードが必要なためです。 そもそもこの取得を一度にやろうとせず、もうちょっと考えるべきでしょうか。 status='3'でやろうとしている他の処理次第です。 要件次第でもしかしたらSQL一発投げるだけで終わる可能性もあります。
uthio

2019/07/12 02:31 編集

コメントありがとうございます。 status='3'でやる処理は、statusが3の場合でupdateが現在の日時を過ぎた場合、そのレコードのstatusを4にしてflagを1にする、といったことになります。(updateは公開日、という位置づけで未来の日付になっているのがあります) つまりまずその処理を行った上で、今回質問に上げた処理を行いたい状態です。
yambejp

2019/07/12 02:47

SQL側でやってもよいのでしょうか?
uthio

2019/07/12 02:54

>yambejp様 コメントありがとうございます。 SQL側でやる、というのがすみません、理解しきれてないですが、むしろ最終的にはSQLを更新するのが目的になります。 特に表示させる必要はなく、実行用のPHPを作ろうと思っています。 これで答えとしては正しいでしょうか…?
yambejp

2019/07/12 02:59 編集

そういうことならSQLでstatusが4でkindがダブっている古い日付のstatusを0にするという 処理を書けばいいような・・・
uthio

2019/07/12 03:13

statusが4の時にそういう処理を書いたSQLを書く、という認識で大丈夫ですか? なるほど、そもそもSQLでそういう処理ができる方法を知りませんでした。。 知識不足ですみませんでした。 もうちょっと探してみます。
guest

回答2

0

ベストアンサー

SQLで処理

SQL

1CREATE TABLE tbl( 2no int(11) unsigned auto_increment, 3kind tinyint(3) unsigned, 4flag tinyint(4), 5status tinyint(4) DEFAULT 0, 6`update` date, 7primary key (no) 8); 9 10insert into tbl values 11( 8, 5,1,4,"2014-08-20"), 12( 15, 3,0,3,"2016-12-25"), 13( 22, 6,1,4,"2017-03-01"), 14( 48, 9,1,4,"2018-05-22"), 15( 52, 5,1,4,"2014-03-04"), 16( 55,23,1,4,"2015-09-28"), 17(104, 2,0,3,"2018-11-11"), 18(107, 3,1,4,"2015-04-28"), 19(109, 1,0,3,"2016-10-15"), 20(116,23,1,4,"2018-07-10"), 21(131,11,0,3,"2013-01-02");

だとして
statusが4で、kindがダブっていて、最新ではないデータはこう

SQL

1select * from tbl as t1 2where exists( 3select 1 from tbl 4where status=t1.status 5and kind=t1.kind 6and `update`>t1.`update` 7) 8and status=4

上記を応用してupdate

SQL

1update tbl set status=0 2where no in(select no from( 3select no from tbl as t1 4where exists( 5select 1 from tbl 6where status=t1.status 7and kind=t1.kind 8and `update`>t1.`update` 9) 10and status=4 11) as sub)

投稿2019/07/12 03:33

yambejp

総合スコア114829

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uthio

2019/07/12 03:56

何から何までありがとうございます。 SQLの知識不足が根本的に問題ですね。。 PHPで無理やりやろうと思ったところから改めねばなりません。 頂いたものでどうにか対応できる気がします。 まず中身をしっかり把握して進めます。 また終わりましたらこの場を借りてご報告いたします。 取り急ぎお礼まで。
uthio

2019/07/22 05:47

こちら回答が大変遅くなり失礼しました。 お陰様で解決しましたし、そもそもSQLの知識が足りないということも気付かせていただき、誠にありがとうございました。
guest

0

PHPでやるなら

php

1$list = [ 2 [ "no" => 8 ,"kind" => 5 ,"flag" => 1, "status" => 4, "update" => "2014-08-20" ], 3 [ "no" => 15 ,"kind" => 3 ,"flag" => 0, "status" => 3, "update" => "2016-12-25" ], 4 [ "no" => 22 ,"kind" => 6 ,"flag" => 1, "status" => 4, "update" => "2017-03-01" ], 5 [ "no" => 48 ,"kind" => 9 ,"flag" => 1, "status" => 4, "update" => "2018-05-22" ], 6 [ "no" => 52 ,"kind" => 5 ,"flag" => 1, "status" => 4, "update" => "2014-03-04" ], 7 [ "no" => 55 ,"kind" => 23 ,"flag" => 1, "status" => 4, "update" => "2015-09-28" ], 8 [ "no" => 104 ,"kind" => 2 ,"flag" => 0, "status" => 3, "update" => "2018-11-11" ], 9 [ "no" => 107 ,"kind" => 3 ,"flag" => 1, "status" => 4, "update" => "2015-04-28" ], 10 [ "no" => 109 ,"kind" => 1 ,"flag" => 0, "status" => 3, "update" => "2016-10-15" ], 11 [ "no" => 116 ,"kind" => 23 ,"flag" => 1, "status" => 4, "update" => "2018-07-10" ], 12 [ "no" => 131 ,"kind" => 11 ,"flag" => 0, "status" => 3, "update" => "2013-01-02" ], 13]; 14$list_a = []; //status4の配列 15 16//status4 のデータ配列を作る SQLから取れるならとったほうがいい。 17for ($i = 0; $i < count($list); $i++) { 18 if($list[$i]["status"] == 4){ 19 array_push($list_a,$list[$i]); 20 } 21} 22 23//メイン処理 24for ($i = 0; $i < count($list_a); $i++) { 25 for ($j = $i+1; $j < count($list_a); $j++) { 26 if($list_a[$i]["kind"] == $list_a[$j]["kind"]){ 27 if($list_a[$i]["update"] > $list_a[$j]["kind"]){ 28 $list_a[$j]["flag"] = 0; 29 $list_a[$j]["status"] = 0; 30 print_r($list_a[$j]); //printの代わりにSQLをアップデート 31 }else { 32 $list_a[$i]["flag"] = 0; 33 $list_a[$i]["status"] = 0; 34 print_r($list_a[$i]); //printの代わりにSQLをアップデート 35 } 36 } 37 } 38} 39

投稿2019/07/12 03:51

zushi0905

総合スコア683

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uthio

2019/07/12 03:59

ご丁寧にありがとうございます。 なるほどです、私が当初やりたかったことはこういうやり方で可能なのですね。 こちらもきちんと内容確認して対応してみたいと思います。 yambejp様からいただいたものも含めて、終わりましたら改めてご報告いたします。 まずはお礼を伝えさせてください。ありがとうございました。
uthio

2019/07/22 05:49

こちら返答が大変遅くなってしまってすみません。 頂いたもので動作を試したところ、私がやりたい通りのことができました。 ただそもそも私の知識不足のせいなのですが、最終的には別のやり方で対応することになってしまいました。 お時間頂いたにも関わらずすみませんでした。 せめてお礼だけこの場でお伝えさせてください。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問