Wybierz mySQL na podstawie tylko miesiąca i roku

102

Mam kolumnę w mojej bazie danych MySQL, która ma kilka wierszy. Jeden z tych wierszy to DATA, na przykład:2012-02-01

To, co chcę osiągnąć, to zrobić SELECT z PHP na podstawie tylko roku i miesiąca.

Logika SELECT będzie następująca:

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

Konkretny miesiąc i rok zostaną przekazane ze $_POSTzmiennej, takiej jak ta$_POST['period']="2012-02";

Jak mogę to zrobić?

DiegoP.
źródło
2
Możesz skorzystać z oświadczenia BETWEEN
Ben Carey,

Odpowiedzi:

208
SELECT * FROM projects WHERE YEAR(Date) = 2011 AND MONTH(Date) = 5
Rick Kuipers
źródło
5
Twoje zapytanie nie będzie skalowane, ponieważ musi wykonać pełne skanowanie tabeli, chyba że w MySQL jest pewna optymalizacja, której nie jestem świadomy.
aefxx
2
Czy to prawda EXTRACT(YEAR_MONTH FROM Date)?
cmbuckley
19

Jeśli masz

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

Najpierw znajdź pierwszy dzień miesiąca:

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

Następnie to zapytanie użyje indeksu, Datejeśli taki masz:

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

Można również użyć włącznie niewyłączne interwały, które działają całkiem dobra (nie trzeba się martwić, jeśli kolumna jest DATE, DATETIMEalbo TIMESTAMP, ani o precyzji:

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

Ostrzeżenie bezpieczeństwa:

Powinieneś odpowiednio uciec od tych wartości lub użyć przygotowanych instrukcji. Krótko mówiąc, użyj dowolnej metody zalecanej obecnie w PHP, aby uniknąć problemów z iniekcją SQL.

ypercubeᵀᴹ
źródło
2
Tak, +1 pomiędzy, początkowo używałem funkcji Rok + Miesiąc, ale takie nie skalowały ani nie używały indeksów.
sobelito
@sobelito Yeah. Zwykle wolę interwały obejmujące wyłączność. Zaktualizowano post.
ypercubeᵀᴹ
Ucieknij przed tymi wartościami lub użyj przygotowanych oświadczeń ... 😓
Jared
9

Proszę bardzo. Zostaw obliczenia PHP i zaoszczędź trochę pracy w DB. W ten sposób możesz efektywnie wykorzystać indeks Datekolumny.

<?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
    );

EDYCJA
Zapomniałem o konwersji znacznika czasu systemu Unix.

aefxx
źródło
Jest przyjazny dla indeksów, ale strtotime daje ci int i musisz najpierw przekonwertować go na aktualny dla mysql.
piotrm
Powinna to być konkatenacja ciągów, a nie operacja $end = strtotime($date .' 1 month - 1 second');
sumująca
6
$q="SELECT * FROM projects WHERE YEAR(date) = 2012 AND MONTH(date) = 1;
Arjan
źródło
6

Załóżmy, że masz pole bazy danych created_at, w którym pobierasz wartość ze znacznika czasu. Chcesz wyszukiwać według roku i miesiąca od daty utworzenia.

YEAR(date(created_at))=2019 AND MONTH(date(created_at))=2
nazmulhaqued
źródło
3

Tutaj ZNAJDŹ rekord według MIESIĄCA i DATY w mySQL

Oto Twoja wartość POST $_POST['period']="2012-02";

Po prostu rozbij wartość myślnikiem $Period = explode('-',$_POST['period']);

Pobierz tablicę z wartości rozstrzelenia:

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

Wpisz wartość w zapytaniu SQL:

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

Uzyskaj wynik według miesiąca i roku.

chintan mahant
źródło
2

aby uzyskać wartości miesiąca i roku z kolumny daty

select year(Date) as "year", month(Date) as "month" from Projects
PAULDAWG
źródło
2

Możesz zrobić tak:

$q="SELECT * FROM projects WHERE Year(Date) = '$year' and Month(Date) = '$month'";
Andreas Helgegren
źródło
1
To również nie używa indeksu
Thijs Riezebeek
1

Logika będzie wyglądać następująco:

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

LIKEOperator wybierze wszystkie wiersze, które zaczynają się $_POST['period']następnie łącznik i dzień mont

http://dev.mysql.com/doc/refman/5.0/en/pattern-matching.html - dodatkowe informacje

Hristo Petev
źródło
4
-1 Operacje na łańcuchach na danych wewnętrznie reprezentowanych jako liczby całkowite !? Poważnie?
aefxx
@Yaroslav Tak, bardzo wydajne, przypuszczam: D
aefxx
2
Bez indeksu. Najpierw konwertuje wartość daty na ciąg, a następnie dopasowuje ten ciąg. W MySQL można zapytać o dowolny typ kolumny za pomocą polecenia LIKE. Ale nadal będzie działać: D
Jarosław
2
Mały bobby ktoś stoły?
Rob
Nie ma potrzeby ciągłego szaleństwa na punkcie wydajności, teraz masz rację. Czasami wysiłek i czas, który wkładasz w coś, aby działało o kilka mikrosekund szybciej, nie robi żadnej różnicy, ale straciłeś ten czas.
Hristo Petev
0

Oto zapytanie, którego używam i zwróci każdy rekord w okresie jako sumę.

Oto kod:

$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();
?>

Zawiera listę każdego emp_nr i sumę godzin miesięcznych, które zgromadziły.

Frank Casser
źródło
0

możesz to zrobić, zmieniając $ q na to:

$q="SELECT * FROM projects WHERE YEAR(date) = $year_v AND MONTH(date) = $month_v;
Symon265
źródło
-1

Tak, to działa, ale zwraca tylko jeden wiersz, podczas gdy jest kilka wierszy do pobrania przy użyciu tylko wybranych kolumn. Podobnie jak SELECT Title, Date FROM mytable WHERE YEAR (Date) = 2017 AND MONTH (Date) = 09 zwraca tylko jeden wiersz.

BLOGBIR
źródło