1

私はこれが奇妙であることを知っています。列タイプが でscheduleある列で呼び出されるテーブルがあります。この列には、2012 年 11 月 1 日から 2013 年 1 月 2 日までの日付 (YYYY-MM-DD 形式) があります。2012-12-01 を含む任意の日付を入力すると、ループが再開されます。したがって、2012-11-15 から 2012-12-15 を選択すると、11 月 15 日から 12 月 1 日まで印刷されますが、12 月 1 日以降は 11 月 15 日に印刷が再開されます。2012-11-15 から 2012-11-30 または 2012-12-02 から 2012-12-30 を選択すると、すべて正常に動作しますが、問題が発生するのはその特定の日付が関係している場合だけです。これが私のコードです:DateDATE

<?php
////////////////////////////////////////////////////////
//////First set the date range that we want to use//////
////////////////////////////////////////////////////////

if(isset($_POST['from']) && ($_POST['from'] != NULL))
    {
    $startDate = $_POST['from'];
    echo "<script>alert (\"startDate: " . $startDate . "\")</script>";
    }
else
    {
    //Default date is Today
    $startDate = date("Y-m-d");
    echo "<script>alert (\"startDate: " . $startDate . "\")</script>";
    }
if(isset($_POST['to']) && ($_POST['to'] != NULL))
    {
    $endDate = $_POST['to'];
    echo "<script>alert (\"endDate: " . $endDate . "\")</script>";
    }
else
    {
    //Default day is one month from today
    $endDate = date("Y-m-d", strtotime("+1 month"));
    echo "<script>alert (\"endDate: " . $endDate . "\")</script>";
    }

//////////////////////////////////////////////////////////////////////////////////////
//////Next calculate the total amount of days selected above to use as a limiter//////
//////////////////////////////////////////////////////////////////////////////////////

    $dayStart = strtotime($startDate);
    $dayEnd = strtotime($endDate);
    $total_days = abs($dayEnd - $dayStart) / 86400 +1;
    echo "<script>alert (\"Total Days: " . $total_days . "\")</script>";

//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////Then we're going to get the date range specified from the schedule table and print the results//////
//////////////////////////////////////////////////////////////////////////////////////////////////////////

//Select the dates from the schedule table, limited to the total amount days.
$sql = ("SELECT Date FROM schedule WHERE Date BETWEEN '$startDate' AND '$endDate' LIMIT $total_days");

//Run a check on the query to make sure it worked. If it failed then print the error.
if(!$result_date_query = $mysqli->query($sql))
    {
    die('There was an error getting the date from the schedule table [' . $mysqli->error . ']');
    }

//Loop through the results while a result is being returned.
while($row = $result_date_query->fetch_assoc())
    {
    //First format and then print the all the dates selected.
    echo "<td class=\"schedule_date_cell\">" . date('M j', strtotime($row['Date'])) . "</td>";
    }

//Free the result.
$result_date_query->free();
?>

私は途方に暮れています。何が起こっているかを示すためにいくつかのエコーステートメントを追加しましたが、すべてが期待どおりです。前のすべての日付と後のすべての日付が完全に機能する方法を理解していませんが、12月1日が含まれているとループが再開されます。関連性があるかどうかはわかりませんが、列に同じ日付が複数あるためLIMIT、クエリに設定しました。

答えを知りたくてたまらないので、誰かがこの事件を大々的に解き明かしてくれることを願っています!

**編集:**コメントで提案されているように、PHPmyadmin内からこの同じクエリを試しましたが、同じ結果が得られました。LIMITまた、単一引用符'2012-11-01'から二重引用符に変更するだけでなく"2012-11-01"、同じ結果で削除しようとしました。

**編集 2: **Date列の各日付について、各日付の 92 のインスタンスがあります。したがって、たとえば、2012-12-01 の 92 レコードと 2012-12-02 の 92 レコードなどがあります。興味深いことにLIMIT、クエリから削除して 2012-11-30 から 2012-12-15 (11 月 30 日から 12 月 15 日) の日付範囲を使用すると、11 月 29 日、11 月 30 日、12 月 1 日が印刷され、これら 3 つの日付が繰り返されます。何度でも92回!その後、残りの 12 月 2 日、12 月 3 日、12 月 4 日、12 月 15 日の印刷を開始し、これらの日付を 92 回繰り返します。これは、11 月 1 日から 11 月 3 日までの日付範囲を入力すると、92 回繰り返す前に範囲内のすべての日付を出力するため、何らかの理由でループが 12 月 1 日に再開されることを証明しています。その理由はLIMIT各日付のすべてのインスタンスを返さないようにするためだったので、11 月 1 日から 11 月 3 日までを 92 回ではなく 1 回だけ取得しますが、制限を解除すると、12 月 1 日が奇妙な問題を引き起こしていることがわかります。

**編集 3: **2012 年 11 月 1 日から 2013 年 1 月 2 日までの同じ日付範囲を入力して同じ新しいテーブルを作成しましたschedule2schedule、今回はそれぞれのインスタンスが 1 つだけです。次に、クエリを再度実行したところ、どの日付の組み合わせでも完全に機能しました。したがって、明らかに問題は、テーブルにこの日付のインスタンスが複数あることですが、scheduleなぜそれが問題なのかわかりません。whileこの日付がループにどのような影響を与えているのかわかりません。そして、あなたがそれを提案する前に、はい、テーブルに同じ日付の複数のインスタンスが必要です;)

4

3 に答える 3

2

LIMIT句を使用する必要はありません。代わりに、クエリを変更して、日付が複数回返されないようにします。

SELECT DISTINCT(Date) FROM schedule WHERE Date BETWEEN '$startDate' AND '$endDate'

これにより、各日付が一度だけ表示されます。

おそらくDate列にインデックスがあり (これは良いことです)、インデックスは 12 月の日付の前に 11 月のすべての日付を並べ替えます (少なくとも同じ年)。また、12 月に開始して 1 月に終了する日付範囲でも同じ問題が発生します。

于 2012-11-23T06:50:33.127 に答える
1

12 月 1 日にループするという事実は、ほとんどの場合、単なる偶然です。MySQL が内部でどのように機能するかの詳細はわかりませんが、順序を指定しないと、要求時にデータにどのような順序でも適用されます。

これを日付が重複しているという事実と組み合わせると、明らかな理由もなく自発的に発生したと説明した状況に陥ります.

各日付を正確に 1 回だけ表示し、それらを時系列で表示する必要があるため、クエリを作成するときにこれら 2 つのことを MySQL に伝える必要があります。そのため、DISTINCTANDORDER BYコマンドを追加します。

SELECT DISTINCT(Date) FROM schedule WHERE Date BETWEEN '$startDate' AND '$endDate' ORDER BY Date ASC
于 2012-11-23T18:26:01.410 に答える
0

UNIQUE特定の日付のエントリを定義する列にインデックスを追加することで、重複を防ぐことができたはずです。

データをクリーンアップして重複を削除した場合、これは事後に簡単に追加できます。

ALTER TABLE schedule ADD UNIQUE INDEX index_on_date (date)

別の方法として、日付ごとに 1 つの行のみを選択する方法があります。これは通常GROUP BY date、クエリの最後に追加することになります。

于 2012-11-23T06:38:23.113 に答える