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

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

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

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

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

Q&A

解決済

1回答

1874閲覧

laravel/php 同じ意味のSQLで違う結果

tktail

総合スコア72

Laravel

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

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

0グッド

0クリップ

投稿2022/01/11 02:45

こんにちは。
売上テーブルが存在し、複数のユーザーが紐づけされています。
売上テーブルにはpublish(timestamp)があり、指定する1週間ごとの日付とユーザーで絞り込みを行いたいと考えます。

$usersには['1', '2', '3']配列。
$wvには[['2021-01-01','2021-01-02','2021-01-03'.'2021-01-04'.'2021-01-05'.'2021-01-06'.'2021-01-07'],[...............]]1週間ごとの日付。
$wv2には[['2021-01-01']['2021-01-07'],['2021-01-08']['2021-01-14']]のように週頭と週終わりを入れています。

色々な方法を試してみてはいますが、以下の2つが思い浮かびました。
①のコードは1週間分の日付をそれぞれforeachで回し、それが4週間分なので4回ループさせています。
②のコードは(①が遅かったので書きました)whereBetweenで範囲抽出を行っています。

しかしdumpすると明らかに取得できた結果が違います。。
これはどちらが正しいというか、どういう挙動でこうなっているのでしょうか?
ご存じの方いらっしゃいましたら、ご回答よろしくお願い致します。

① for ($i=0; $i<4; $i++){ foreach ($wv[$i] as $key => $val) { $cnt[$i] = Uriage::whereIn('id', $users) ->whereDate('publish', $val) ->count(); } } dump($cnt); // array:4 [▼0 => 21 1 => 29 2 => 18 3 => 14] ② $cnt2 = array(); foreach($wv2 as $key => $val){ $cnt2[$key] = Uriage::whereIn('id', $users) ->whereBetween('publish', $val) ->count(); } dump($cnt2); // array:4 [▼0 => 171 1 => 118 2 => 160 3 => 176]

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2022/01/11 02:58

publishというカラムのデータ型は何でしょうか、あとDBの処理系はmysqlでしょうか。
tktail

2022/01/11 03:02

DBはposgreSQLで、publishはtimestampになります。 よろしくお願い致します。
Orlofsky

2022/01/11 07:41

SQLではテーブル定義は大切です。質問にCREATE TABLEくらいは提示されては?
guest

回答1

0

ベストアンサー

①の->whereDate('publish', $val)って動きました? 配列で渡してOKだったっけ?と。
動いているかもう一度確認してみてください。
(可能なら、PostgreSQL全体の設定などでSQL実行ログを出力させてみてください:PostgreSQL 実行されたSQLをログに出力(システム全体の設定) - Kakiro-Web カキローウェブ

一般に日付7つ指定するよりも、betweenで囲んだ方が速そうに思えます。

TIMESTAMP型で日付を扱う時、1秒や1秒未満のマイクロ秒とかちょっとずれてしまっても
一致しなくなってしまうと思うので、
本当に時刻成分なしに比較するなら素直にDATE型で扱った方がよろしいかと。
(比較するときにいちいちDATE型に変換するのは無駄だし。式に対するインデックスを駆使したら少しはマシかも知れませんが。)

SQLに慣れているのであれば、DB::raw(~)でSQL処理系に依存する表記で書いてしまってもいいでしょうし。
->whereRaw("publish between cast(? as timestamp) and cast(? as timestamp) + '6 days'::interval", [$val, $val])
が通じるかどうか。
(?の2箇所をそれぞれ同じ$valで置き換えさせて、クエリ上で6日分日付を足しているつもり。)

あと、余計なお世話かもしれませんが、
カラムidとpublishにはインデックスは設定済みでしょうか?
idがユーザーIDらしいので重複を許すインデックスで、
publishも同じく重複を許すインデックスでしょうね。
SQL実行ログを記録できるように設定変更できていれば、
EXPLAINの利用でクエリー実行パフォーマンスを念の為にチェックしてみると良いです。

投稿2022/01/11 04:35

編集2022/01/11 06:57
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

tktail

2022/01/11 11:15

ご回答ありがとうございます。 ご指摘の通り、動いていませんでした。。汗 またDB::raw(~)を実行しましたところ、betweenと同じ結果になりました。 勉強不足で理解できない部分があるので、かみ砕いて理解しようと思います。ありがとうございます。 両方の速度を算出しましたところ whereRaw:13.865764141083 whereBetween:1.9495930671692 という結果になりました。 既存DBでインデックスは全く貼られておらず、変更も出来ないので仕方ない部分があります。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問