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

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

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

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

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

Q&A

解決済

2回答

1524閲覧

【MYSQL】【PHP】更新時間を基準にしての並び替えを行う方法【初心者】

shimane

総合スコア98

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

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

0グッド

1クリップ

投稿2017/10/20 01:02

現在、PHPとMYSQLの勉強をしながらサイトを作成しています。

記事をデータベースに保存して
mysqlを使ってサイトに表示するという事を行っています。

【事前情報】

記事タイトル
記事URL
カテゴリ名(100種類ぐらいあります。)
更新日時
PV数(ページビュー数)


【やりたい事】

トップページにて「記事を表示」する際に「更新日時」と「PV数」を基準にして
並び替えをしたいです。

単純な更新日時の順番だと「PV数」が少ない人気の無い記事が一番最初に表示される事もあるので
20分以内に更新された記事の中から「PV数が多い順番」に並び替えをしたいと考えております。
(すべての記事を表示しつつ、20分以内に更新された記事の中からPV数の多い順番に並び替え)


【例】
すべての記事を表示させつつ
更新日時が20分以内の記事の中からPV数が多い順番に並び替えを行いたいです。

記事A
カテゴリ:日本
PV:100
更新日時:20分以内

記事B
カテゴリ:アメリカ
PV:90
更新日時:20分以内

記事C
カテゴリ:中国
PV:90
更新日時:20分以内

↑は更新日時が20分以内の記事で、PV数の多い順番に並び替えが成功している状態です。

ここから下にはさらに20分間間隔で
その20分間間隔の記事の中からPV数の多い順番に並び替えが成功している状態です。

記事D
カテゴリ:カナダ
PV:500
更新日時:40分以内

記事E
カテゴリ:アメリカ
PV:900
更新日時:80分以内

記事F
カテゴリ:中国
PV:9000
更新日時:100分以内


【試してみた事】

ネットで色々検索してみた所
希望している完成に近付ける事は出来ました。

更新日時:created
PV数:pv
ページナビゲーション機能に利用:. $offset . "," . $pagelimit

PHP

1$stmt = $db->query("select * from bbs 2 order by date_format( created, '%Y-%m-%d %H:%i' ) desc, pv desc limit " . $offset . "," . $pagelimit); 3 $mysqlall = $stmt->fetchAll(\PDO::FETCH_OBJ); 4

これで更新された記事を1分単位でのPV数が多い順番に並び替えをする事が出来ました。
1分単位だと該当する記事の数が少なすぎて
不人気な記事でも先頭に表示されてしまいます。

ですので、これが1分単位ではなくて「20分間」単位になるのが理想とする形です。

色々試してみた所「1時間単位」には設定する事が出来ました。

PHP

1$stmt = $db->query("select * from bbs 2 order by date_format( created, '%Y-%m-%d %H' ) desc, pv desc limit " . $offset . "," . $pagelimit); 3 $mysqlall = $stmt->fetchAll(\PDO::FETCH_OBJ);

該当する記事が増えたのですが
1時間だと時間があまりにも長すぎるので「20分間」を理想としているのですが上手くいきません。

またこちらの方法でも試してみました。

PHP

1$stmt = $db->query("select * from bbs where created > CURRENT_TIMESTAMP + INTERVAL - 20 MINUTE order by pv desc limit " . $offset . "," . $pagelimit); 2 $mysqlall = $stmt->fetchAll(\PDO::FETCH_OBJ);

上のコードですと「20分間間隔」での「pV数」の並び替えを行う事が出来ましたが
「20分以内の記事だけ」しか表示されず、
すべての記事を表示しつつ「20分間間隔」での「pV数」での並び替えを行う事が出来ませんでした。
(20分以内の記事が10件だけなら、その10件だけが表示されて終わってしまいます。)
(総記事数が1000件でも「10件」だけが表示される事になるので、困っています。)

私なりにネットで調べたり書籍で調べても上手くいきません。

すべての記事を表示しつつ「20分間間隔」での「pV数」での並び替えを行う方法をご存知の方や
解決する為の方法に何か心当たりのある方は教えて頂けないでしょうか?
お力をお貸し頂けると嬉しいです。

どうかよろしくお願いします。

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

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

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

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

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

guest

回答2

0

成功している「1時間間隔+PV数でソート」から、どうやったら「20分間隔」にできるかを考えましょう。

UNIX秒という概念はご存知ですか?1970-01-01 00:00:00から何秒経ったかという時間の概念です。例えば2017-10-20 12:00:00(日本標準時刻)1508468400という数字になります。では秒が分かればこれを20分ごとに分割してやればよいのです。20分は60秒×20分なので2400秒ですね。ではUNIX秒を2400で割って切り捨ててしまえば20分ごとの区切りになります。

TIMESTAMP型からUNIX秒を求めるにはUNIX_TIMESTAMP関数を、切り捨てはFLOOR関数を使います。

PHP

1$stmt = $db->query("select * from bbs 2 order by FLOOR(UNIX_TIMESTAMP(created) / 2400) desc, pv desc limit " . $offset . "," . $pagelimit);

ということで、これで希望の結果になるでしょうか?検証してみてください。

蛇足

SQLに変数を渡す際にはプリペアドステートメントを使いましょう。SQLに文字列として結合して使うやり方はセキュリティ的に超危ない行為です。
http://php.net/manual/ja/pdo.prepared-statements.php

PHP

1$stmt = $db->prepare("select * from bbs 2 order by FLOOR(UNIX_TIMESTAMP(created) / 2400) desc, pv desc limit :offset, :pagelimit"); 3$stmt->bindParam(':offset', $offset, PDO::PARAM_INT); 4$stmt->bindParam(':pagelimit', $pagelimit, PDO::PARAM_INT); 5$stmt->execute(); 6$mysqlall = $stmt->fetchAll(\PDO::FETCH_OBJ);

投稿2017/10/20 01:58

編集2017/10/20 03:07
masaya_ohashi

総合スコア9206

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

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

masaya_ohashi

2017/10/20 02:00

しかもyambejpさんの回答のほうが「現在時刻から逆算して20分区切り」というスマートな方法だったー!
shimane

2017/10/20 02:01

おおお、素晴らしいです。このようにして考えていくのですね、有難うございます!
shimane

2017/10/20 02:01

+評価を贈らせて頂きます、本当にありがとうございます!大感謝です!
masaya_ohashi

2017/10/20 02:11 編集

サンプルを見たとき、「なぜその関数が必要なのか?」を考えていく力がプログラマとしての力になります。 どっちかというと私の回答は実は蛇足のほうが強く推したいことなので、そちらの学習もしっかりとお願いします。
shimane

2017/10/20 02:51

有難うございます。 教えて頂きました「プリペアードステートメント」を早速試してみました。 コード: $stmt = $db->query("select * from bbs order by floor(TIMESTAMPDIFF(MINUTE,created ,now())/20) ASC, pv desc limit :offset, :pagelimit"); $stmt->bindParam(':offset', $offset); $stmt->bindParam(':pagelimit', $pagelimit); $stmt->execute(); $mysqlall = $stmt->fetchAll(\PDO::FETCH_OBJ); その結果エラーが表示されました。 Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':offset, :pagelimit' at line 2' 日本語訳: 致命的なエラー:「SQLSTATE [42000]:構文エラーまたはアクセス違反:1064」というメッセージで、キャッチされていない例外「PDOException」SQL構文にエラーがあります。あなたのMySQLサーバのバージョンに対応するマニュアルをチェックし、正しい構文が ':offset、:pagelimit'の2行目近くで使用するようにしてください。 私なりにこのエラーを解決しようと :offset, :pagelimitを色々と場所を変えたり ネットで検索してみたのですが 上手く解決出来ません。 どこか変なコードの場所がありましたら、教えて頂けると嬉しいです。
masaya_ohashi

2017/10/20 02:56

$db->queryではなく$db->prepareです。私のコードをよく見てください。
shimane

2017/10/20 03:02

これはお恥ずかしいです。 $db->prepareに変更してみます! コード: $stmt = $db->prepare("select * from bbs order by floor(TIMESTAMPDIFF(MINUTE,created ,now())/20) ASC, pv desc limit :offset, :pagelimit"); $stmt->bindParam(':offset', $offset); $stmt->bindParam(':pagelimit', $pagelimit); $stmt->execute(); $mysqlall = $stmt->fetchAll(\PDO::FETCH_OBJ); 実行結果: Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''0', '50'' at line 2' このエラーが表示されました。 なんとか解決出来ればと頑張っているのですが上手くいきません、 お力をお貸し頂ければ嬉しいです。
masaya_ohashi

2017/10/20 03:06

あー、申し訳ない。$offsetや$pagelimitが文字列として扱われてしまっていますね。数値扱いしてもらえるように回答を修正しておきます。
shimane

2017/10/20 03:09

有難うございます!今度からこのエラーが出た時には 今回教えて頂いたような対応をしたいと思います!
shimane

2017/10/20 03:10

おおおお、有難うございます!, PDO::PARAM_INTを追加しましたら 正常にすべてばっちりに表示されました。本当に助かりました! 今後もいっぱいいっぱい勉強を進めていこうと思います!大感謝です!
guest

0

ベストアンサー

floor(TIMESTAMPDIFF(MINUTE,created ,now())/20)

とすれば、20分単位の経過数値がわかります

投稿2017/10/20 01:23

yambejp

総合スコア114572

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

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

shimane

2017/10/20 01:42

yambejpさん回答有難うございます。 教えて頂いたコードを試してみました。 $stmt = $db->query("select * from bbs order by floor(TIMESTAMPDIFF(MINUTE,created ,now())/20)ASC, pv desc limit " . $offset . "," . $pagelimit); $mysqlall = $stmt->fetchAll(\PDO::FETCH_OBJ); 実行結果: まさに理想とする20分間以内の記事のPV数の大きい順番の並び替えを行う事が出来ました! 本当に素晴らしいです。大感謝です!+評価とベストアンサーをさせて頂きます。 助けて頂きまして本当に有難うございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問