月と年のみに基づいてmySQLを選択する


102

行がいくつかあるmySQL DBに列があります。この行の1つは、次のようなDATEです。2012-02-01

私が達成したいのは、年と月のみに基づいてPHPでSELECTを実行することです。

SELECTのロジックは次のようになります。

$q="SELECT * FROM projects WHERE Date="SELECT HERE THE SPECIFIC YEAR AND MONTH"";

特定の月と年は$_POST、このように変数から渡されます$_POST['period']="2012-02";

どうすればできますか?


2
BETWEENステートメントを使用できます
Ben Carey

回答:


208
SELECT * FROM projects WHERE YEAR(Date) = 2011 AND MONTH(Date) = 5

5
MySQLで私が知らない最適化がない限り、全テーブルスキャンを実行する必要があるため、クエリはスケーリングされません。
aefxx

2
これは本当EXTRACT(YEAR_MONTH FROM Date)ですか?
cmbuckley

19

あなたが持っている場合

$_POST['period'] = "2012-02";

まず、月の最初の日を見つけます:

$first_day = $_POST['period'] . "-01"

次に、このクエリは、インデックスがあるDate場合にインデックスを使用します。

$q = "
    SELECT *  
    FROM projects 
    WHERE Date BETWEEN '$first_day' 
                   AND LAST_DAY( '$first_day' )
     " ;

包含的および排他的間隔を使用することもできます。これは非常に効果的です(列がDATEDATETIMEまたはTIMESTAMPであるかどうかや、精度について心配する必要はありません。

$q = "
    SELECT *  
    FROM projects 
    WHERE Date >= '$first_day' 
      AND Date  < '$first_day' + INTERVAL 1 MONTH 
     " ;

セキュリティ警告:

これらの値を適切にエスケープするか、準備されたステートメントを使用する必要があります。つまり、SQLインジェクションの問題を回避するために、最近PHPで推奨されている方法を使用してください。


2
ええ、その間+1、私は最初はYear + Month関数を使用していましたが、それはスケーリングされず、インデックスも使用されませんでした。
sobelito 2015年

@sobelitoうん。私は通常、包含と排他の間隔を好みます。投稿を更新しました。
ypercubeᵀᴹ

これらの値をエスケープするか、プリペアドステートメントを使用して...😓してください
ジャレド

9

どうぞ。コンピューティングをPHPに任せ、DBの作業をいくつか保存します。これにより、Date列のインデックスを効果的に使用できます。

<?php
    $date = $_POST['period'];

    $start = strtotime($date);
    $end   = strtotime($date . ' 1 month - 1 second');

    $query = sprintf(
        'SELECT *
           FROM projects
          WHERE Date BETWEEN FROM_UNIXTIME(%u) AND FROM_UNIXTIME(%u)',
        $start,
        $end
    );

編集
Unixタイムスタンプ変換を忘れました。


インデックスフレンドリーですが、strtotimeはintを提供するため、最初にmysqlの日付に変換する必要があります。
piotrm

:これは、文字列の連結ではなく、和演算する必要があります$end = strtotime($date .' 1 month - 1 second');
コンスタンチンPereiaslov


6

タイムスタンプから値を取得するデータベースフィールドcreated_atがあるとします。created_atの日付から年と月で検索したいとします。

YEAR(date(created_at))=2019 AND MONTH(date(created_at))=2

3

ここでは、mySQLのMONTHおよびDATEでレコードを検索します

ここにあなたのPOST値があります $_POST['period']="2012-02";

ただ、ダッシュで値を爆発させる $Period = explode('-',$_POST['period']);

分解値から配列を取得します。

Array ( [0] => 2012 [1] => 02 )

SQLクエリに値を入力します。

SELECT * FROM projects WHERE YEAR(Date) = '".$Period[0]."' AND Month(Date) = '".$Period[0]."';

月と年ごとに結果を取得します。


2

日付列から月と年の値を取得する

select year(Date) as "year", month(Date) as "month" from Projects


1

ロジックは次のようになります。

SELECT * FROM objects WHERE Date LIKE '$_POST[period]-%';

LIKEオペレータは、で始まるすべての行を選択します$_POST['period']ダッシュとモンの日が続きます

http://dev.mysql.com/doc/refman/5.0/en/pattern-matching.html-いくつかの追加情報


4
-1内部的に整数として表現されたデータに対する-1文字列操作!?本気?
aefxx

@Yaroslavはい、非常に効率的だと思います:D
aefxx 2013年

2
インデックスなし。最初に日付値を文字列に変換し、その文字列と一致させます。MySQLでは、LIKEを使用して任意の列タイプをクエリできます。しかし、それでも動作します:D
Yaroslav '20

2
小さなボビーテーブルは誰ですか?
Rob

いつもパフォーマンスに夢中になる必要はありません。場合によっては、数マイクロ秒速く動作させるために何かに費やした労力と時間は何の違いももたらさない場合がありますが、その時間を失っています。
Hristo Petev

0

これは私が使用するクエリで、期間内の各レコードを合計として返します。

これがコードです:

$result = mysqli_query($conn,"SELECT emp_nr, SUM(az) 
FROM az_konto 
WHERE date BETWEEN '2018-01-01 00:00:00' AND '2018-01-31 23:59:59' 
GROUP BY emp_nr ASC");

echo "<table border='1'>
<tr>
<th>Mitarbeiter NR</th>
<th>Stunden im Monat</th>
</tr>";

while($row = mysqli_fetch_array($result))
{
$emp_nr=$row['emp_nr'];
$az=$row['SUM(az)'];
echo "<tr>";
echo "<td>" . $emp_nr . "</td>";
echo "<td>" . $az . "</td>";
echo "</tr>";
}
echo "</table>";
$conn->close();
?>

これは、各emp_nrと、それらが累積した毎月の時間の合計をリストします。


0

$ qを次のように変更することで実行できます。

$q="SELECT * FROM projects WHERE YEAR(date) = $year_v AND MONTH(date) = $month_v;

-1

ええ、これは機能していますが、選択された列のみを使用して取得する行がいくつかある間、1行のみを返します。SELECT Titleと同様に、Date FROM mytable WHERE YEAR(Date)= 2017 AND MONTH(Date)= 09は1行のみを返します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.