เลือก mySQL ตามเดือนและปีเท่านั้น


103

ฉันมีคอลัมน์ใน mySQL DB ที่มีบางแถว หนึ่งในแถวนี้คือ DATE ดังนี้:2012-02-01

สิ่งที่ฉันต้องการบรรลุคือทำการ SELECT ด้วย PHP โดยพิจารณาจากปีและเดือนเท่านั้น

ตรรกะของ SELECT จะเป็นดังต่อไปนี้:

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

เดือนและปีที่ระบุจะถูกส่งผ่านจาก$_POSTตัวแปรเช่นนี้$_POST['period']="2012-02";

ฉันจะทำมันได้อย่างไร?


2
คุณสามารถใช้คำสั่ง BETWEEN
Ben Carey

คำตอบ:


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

6
แบบสอบถามของคุณจะไม่ปรับขนาดเนื่องจากต้องทำการสแกนแบบเต็มตารางเว้นแต่จะมีการเพิ่มประสิทธิภาพบางอย่างใน MySQL ที่ฉันไม่ทราบ
aefxx

2
นี่คือความจริงสำหรับEXTRACT(YEAR_MONTH FROM Date)?
cmbuckley

20

ถ้าคุณมี

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

ขั้นแรกให้ค้นหาวันแรกของเดือน:

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

จากนั้นแบบสอบถามนี้จะใช้ดัชนีในDateกรณีที่คุณมี:

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

หนึ่งยังสามารถใช้ช่วงเวลารวม แต่เพียงผู้เดียวซึ่งทำงานสวยดี (คุณจะได้ไม่ต้องกังวลถ้าคอลัมน์DATE, DATETIMEหรือTIMESTAMPไม่เกี่ยวกับความแม่นยำ:

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

คำเตือนด้านความปลอดภัย:

คุณควรหลีกเลี่ยงค่าเหล่านี้อย่างเหมาะสมหรือใช้คำสั่งที่เตรียมไว้ ในระยะสั้นใช้วิธีใดก็ได้ที่แนะนำใน PHP ในปัจจุบันเพื่อหลีกเลี่ยงปัญหาการแทรก SQL


2
ใช่ +1 ระหว่างนั้นตอนแรกฉันใช้ฟังก์ชัน Year + Month แต่ไม่ได้ปรับขนาดหรือใช้ดัชนี
sobelito

@sobelito เย้. ฉันมักจะชอบช่วงเวลาที่รวม - พิเศษ อัปเดตโพสต์แล้ว
ypercubeᵀᴹ

โปรดหลีกเลี่ยงค่าเหล่านี้หรือใช้คำสั่งที่เตรียมไว้ ... 😓
Jared

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');
Konstantin Pereiaslov


6

สมมติว่าคุณมีฟิลด์ฐานข้อมูล created_at ที่คุณรับค่าจากการประทับเวลา คุณต้องการค้นหาตามปีและเดือนจากวันที่สร้าง _ ที่

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

3

ที่นี่ค้นหาบันทึกโดย MONTH และ DATE ใน mySQL

นี่คือค่า POST ของคุณ $_POST['period']="2012-02";

เพียงแค่ระเบิดค่าด้วยเส้นประ $Period = explode('-',$_POST['period']);

รับอาร์เรย์จากค่าการระเบิด:

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

ใส่ค่าใน SQL Query:

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

รับผลลัพธ์ตามเดือนและปี


2

ตรรกะจะเป็น:

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 การดำเนินการสตริงกับข้อมูลที่แสดงภายในเป็นจำนวนเต็ม!? คุณจริงจัง?
aefxx

@Yaroslav ใช่ประสิทธิภาพสูงฉันคิดว่า: D
aefxx

2
ไม่มีดัชนี ขั้นแรกจะแปลงค่าวันที่เป็นสตริงและตรงกับสตริงนั้น ใน MySQL คอลัมน์ทุกประเภทสามารถสอบถามได้โดย LIKE แต่ก็ยังใช้ได้: D
Yaroslav

2
บ๊อบบี้โต๊ะเล็ก ๆ ใคร?
Rob

ไม่จำเป็นต้องคลั่งไคล้ในการแสดงตลอดเวลาตอนนี้คุณ บางครั้งความพยายามและเวลาที่คุณทุ่มเทเพื่อให้มันทำงานได้เร็วขึ้นสองสามไมโครวินาทีก็ไม่ได้สร้างความแตกต่าง แต่คุณเสียเวลาไปแล้ว
Hristo Petev

2

เพื่อรับค่าเดือนและปีจากคอลัมน์วันที่

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


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

ไม่มีใครดูเหมือนว่าจะพูดคุยเกี่ยวกับผลการปฏิบัติงานเพื่อให้ผมทดสอบสองคำตอบที่นิยมมากที่สุดในฐานข้อมูลตัวอย่างจาก Mysql ตารางมี 2.8 ล้านแถวพร้อมโครงสร้าง

CREATE TABLE `salaries` (
  `emp_no` int(11) NOT NULL,
  `salary` int(11) NOT NULL,
  `from_date` date NOT NULL,
  `to_date` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

ALTER TABLE `salaries`
  ADD PRIMARY KEY (`emp_no`,`from_date`);

นี่คือการทดสอบที่ดำเนินการและผลลัพธ์

SELECT * FROM `salaries` WHERE YEAR(from_date) = 1992 AND MONTH(from_date) = 6
12339 results
-----------------
11.5 ms 
12.1 ms
09.5 ms
07.5 ms
10.2 ms
-----------------
10.2 ms Avg
-----------------


SELECT * FROM `salaries` WHERE from_date BETWEEN '1992-06-01' AND '1992-06-31'
-----------------
10.0 ms
10.8 ms
09.5 ms
09.0 ms
08.3 ms
-----------------
09.5 ms Avg
-----------------


SELECT * FROM `salaries` WHERE YEAR(to_date) = 1992 AND MONTH(to_date) = 6
10887 results
-----------------
10.2 ms
11.7 ms
11.8 ms
12.4 ms
09.6 ms
-----------------
11.1 ms Avg
-----------------


SELECT * FROM `salaries` WHERE to_date BETWEEN '1992-06-01' AND '1992-06-31'
-----------------
09.0 ms
07.5 ms
10.6 ms
11.7 ms
12.0 ms
-----------------
10.2 ms Avg
-----------------

ข้อสรุปของฉัน

  1. BETWEEN ดีขึ้นเล็กน้อยทั้งในคอลัมน์ที่จัดทำดัชนีและไม่ได้จัดทำดัชนี
  2. คอลัมน์ที่ไม่ได้จัดทำดัชนีช้ากว่าคอลัมน์ที่จัดทำดัชนีเล็กน้อย

-1

ใช่มันใช้งานได้ แต่จะส่งคืนหนึ่งแถวในขณะที่มีหลายแถวเพื่อดึงข้อมูลโดยใช้คอลัมน์ที่เลือกเท่านั้น เช่นเดียวกับชื่อที่เลือกวันที่จาก mytable WHERE YEAR (วันที่) = 2017 และเดือน (วันที่) = 09 ส่งกลับเพียงแถวเดียว

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.