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

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

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

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

PHP

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

Q&A

4回答

1444閲覧

更新日が違う物・DBに無いデータのみ抽出したい

ms5025

総合スコア292

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

PHP

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

0グッド

0クリップ

投稿2020/02/19 01:12

編集2020/02/19 01:12

前提・実現したいこと

前提
postgreSQL
言語php
フレームワーク Laravel

DBのデータ key=id

id=1 name=ピアノ last_update_time=2019/01/01 01:01:01 id=2 name=カバン last_update_time=2019/01/01 01:01:01

更新用配列(array)

list[ id=1 name=ピアノ last_update_time=2019/01/01 01:01:01 , id=2 name=カバン last_update_time=2019/01/31 10:01:01 , id=3 name=筆箱 last_update_time=2019/02/01 10:01:01 ]

■実現したいこと
・更新用対象配列の値の中で
対応するDBTableのlast_updated_timeが違う物・またはDBに無いデータを取得したいです。

上記の例で言えば
id = [2,3]
というidの配列を取得したいです

id=1 同じデータだから必要なし
id=2 更新日が違うから必要あり
id=3 DBに存在していない、新規の値だから必要あり

ということです

■聞きたいこと
取得を実現する為にSQL一本で可能かどうか

■試したこと・考え
①更新用配列を一件ずつループして、
idと更新日が同じデータがないselect文を発行し、データ0件の場合のみ、id[] にプッシュしていく、という方法

②更新用配列を一件ずつループして、動的SQLを作成して一回で取る方法
(db.id= 配列1[id][index] and db.last_update_time = 配列[index][last_update_time] OR)
というような条件文をループで繋げてselect文を作り、その配列と更新用配列のdeffを結果とする方法

できれば上記のような配列ループなどをせず、一本のsqlで組みたいのですが
実現可能でしょうか??

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

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

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

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

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

guest

回答4

0

こんなやり方もあるかなぁと思って記述してみました。

$data = DBのデータ(クエリビルダを利用してwhereinでidが同じものを      列名idとlast_update_timeをselectした単純なSQL文) $list = 配列 $compare = function ($x, $y) { return $x['id'] <=> $y['id'] ?: $x['last_update_time'] <=> $y['last_update_time']; }; var_dump(array_merge( array_udiff($list, $data, $compare), array_udiff($data, $list, $compare) )); これで差異のある配列 (例 array:2 [ 0 => array:2 [ "id" => 2 "last_update_time" => "2019/01/31 10:01:01" ] 1 => array:2 [ "id" => 3 "last_update_time" => "2019/02/01 10:01:01" ] ] コード id = [2,3]

が取れるかなと思うのですがどうでしょうか?
配列操作は時間がかかるでしょうか?

投稿2020/02/19 03:59

編集2020/02/19 04:03
ms5025

総合スコア292

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

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

0

あくまで「ループしない」という条件を満たすための方法として提案してみます。
※実処理として「おススメするかどうか」は別の話です。更新用配列のサイズが小さいなら、ループしたほうが早いかと……。

1.更新用配列を別テーブル(テンポラリテーブル)に入れる。

2.下記のクエリを発行する(テンポラリテーブルから、元テーブルと「idと最終更新時が一致するもの"以外"」を取得)。
※元テーブルを org 、「更新用配列を入れたテンポラリテーブル」を tmp としています。

sql

1SELECT * FROM tmp 2WHERE NOT EXISTS( 3 SELECT * FROM org 4 WHERE 5 org.id = tmp.id 6 AND 7 org.last_updated_time = tmp.last_updated_time 8)

動作検証はしていないので、あくまでイメージ図ということでお願いします。

投稿2020/02/19 03:04

nak

総合スコア696

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

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

ms5025

2020/02/19 04:02

ありがとうございます。ループしたほうが早いということでしたら そちらにしようかと思います。 量はわかりませんが、あるときは何千単位であるかと思います。 なので迷っていまして・・・ 10,20件の運用場所もあるし 何千単位の運用場所もある、といったところです
guest

0

**unnest()**で配列を行に展開できますので、展開した結果で比較すればSQLのみで可能です。
9.18. 配列関数と演算子

また、POSTGRESは構造体(Type)同士での比較が可能です。
Type定義を行いその構造体にCASTして比較を行うと、記述は簡潔になります。
CREATE TYPE

追記

full outer join (全外部結合)を使用して比較します。

SQL

1with list as ( 2 select * from (values 3 (1, 'ピアノ', '2019/01/01 01:01:01'::timestamp) 4 ,(2, 'カバン', '2019/01/31 10:01:01'::timestamp) 5 ,(3, '筆箱', '2019/02/01 10:01:01'::timestamp) 6 ) as w(id, name, last_update_time) 7) 8select coalesce(tbl.id, list.id) as id 9from tbl full outer join list 10 on tbl.id=list.id 11where tbl.id is null 12 or tbl.last_update_time!=list.last_update_time

投稿2020/02/19 02:29

編集2020/02/19 03:05
sazi

総合スコア25300

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

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

ms5025

2020/02/19 02:39

ありがとうございます。 Type定義は今の開発環境では難しいです。 また、unnest()で縦展開できても、id とlast_update_timeの紐付けは どのようにするのでしょうか・・・
sazi

2020/02/19 02:52 編集

unnest()で展開したものとテーブルとの比較です。 MasakinさんのValuesの方が記述は簡単になりそうですけど、展開したものを比較するのは同じですよ。
ms5025

2020/02/19 03:02

idを縦展開したテーブル last_update_timeを縦展開したテーブル この2つの紐付けはどうしたらいいんだろうと思いまして。 id=1 and last_update_time=1 のデータがDBにあるかどうか というsqlが必要かなと思ったのですが。 検討違いでしたらすいません
sazi

2020/02/19 03:07

追記しました。
ms5025

2020/02/19 04:02

ありがとうございます! やはりこの形になりますか!
guest

0

検索結果のループはOKですか?

比較するDBはtt1としています。

SQL

1with sel as (select * from (values 2 (1, 'ピアノ', '2019/01/01 01:01:01'::timestamp), 3 (2, 'カバン', '2019/01/31 10:01:01'::timestamp), 4 (3, '筆箱', '2019/02/01 10:01:01'::timestamp) 5 ) as a(id, name, last_update_time)) 6select id from sel 7 where id = (select sel.id from sel left join tt1 on sel.id = tt1.id 8 where tt.id is null) 9 or id in (select sel.id from sel inner join tt1 on sel.id = tt1.id 10 where sel.last_update_time <> tt1.last_update_time)

はじめのwith句作成時の配列ループは必要ですが、1本のSQLでいけそうです。
条件部分がもう少しきれいにできそうですが・・・

投稿2020/02/19 02:12

Masakin

総合スコア192

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

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

ms5025

2020/02/19 02:17

ありがとうございます! やはり条件文をループで作成する形になりますよね?? むしろこれ以外方法ってない感じですよね・・・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問