Sélectionnez mySQL uniquement en fonction du mois et de l'année


102

J'ai une colonne dans ma base de données mySQL qui contient quelques lignes. L'une de ces lignes est un DATE, comme ceci:2012-02-01

Ce que je veux réaliser est de faire un SELECT avec PHP basé uniquement sur l'année et le mois.

La logique du SELECT sera la suivante:

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

Le mois et l'année spécifiques seront transmis à partir d'une $_POSTvariable, comme celle-ci$_POST['period']="2012-02";

Comment puis-je le faire?


2
Vous pouvez utiliser l'instruction
Ben Carey

Réponses:


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

5
Votre requête ne sera pas mise à l'échelle car elle doit effectuer une analyse complète de la table, sauf s'il existe une optimisation dans MySQL dont je ne suis pas au courant.
aefxx

2
Est-ce vrai pour EXTRACT(YEAR_MONTH FROM Date)?
cmbuckley

19

Si tu as

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

Tout d'abord, recherchez le premier jour du mois:

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

Ensuite, cette requête utilisera un index Datesi vous en avez un:

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

On pourrait également utiliser des intervalles inclusifs exclusifs, qui fonctionnent plutôt bien (vous n'avez pas à vous soucier de savoir si la colonne est DATE, DATETIMEou TIMESTAMP, ni sur la précision:

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

Avertissement de sécurité:

Vous devez correctement échapper ces valeurs ou utiliser des instructions préparées. En bref, utilisez la méthode recommandée de nos jours en PHP, pour éviter tout problème d'injection SQL.


2
Ouais, +1 pour l'intervalle, j'utilisais initialement les fonctions Année + Mois, mais celles-ci n'utilisaient pas de mise à l'échelle ni d'index.
sobelito

@sobelito Ouais. Je préfère généralement les intervalles inclusifs exclusifs. Message mis à jour.
ypercubeᵀᴹ

Veuillez échapper à ces valeurs ou utiliser des instructions préparées ... 😓
Jared

9

Voici. Laissez le calcul à PHP et enregistrez votre base de données. De cette façon, vous pouvez utiliser efficacement un index sur la Datecolonne.

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

EDIT
J'ai oublié la conversion d'horodatage Unix.


Il est compatible avec les index, mais strtotime vous donne un int et vous devez d'abord le convertir en date pour mysql.
piotrm

Il devrait s'agir d'une concaténation de chaînes plutôt que d'une opération de somme:$end = strtotime($date .' 1 month - 1 second');
Konstantin Pereiaslov

6
$q="SELECT * FROM projects WHERE YEAR(date) = 2012 AND MONTH(date) = 1;

6

Supposons que vous ayez un champ de base de données created_at où vous prenez la valeur de l'horodatage. Vous souhaitez effectuer une recherche par année et par mois à partir de la date created_at.

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

3

Ici, TROUVEZ l'enregistrement par MOIS et DATE dans mySQL

Voici votre valeur POST $_POST['period']="2012-02";

Juste, exploser la valeur par tiret $Period = explode('-',$_POST['period']);

Obtenez le tableau à partir de la valeur d'explosion:

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

Mettez de la valeur dans la requête SQL:

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

Obtenez le résultat par MOIS et ANNÉE.


2

pour obtenir les valeurs du mois et de l'année à partir de la colonne de date

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


1

La logique sera:

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

L' LIKEopérateur sélectionnera toutes les lignes commençant par $_POST['period']suivi d'un tiret et du jour du mont

http://dev.mysql.com/doc/refman/5.0/en/pattern-matching.html - Quelques informations supplémentaires


4
-1 Opérations de chaîne sur les données représentées en interne sous forme d'entier !? Es tu sérieux?
aefxx

@Yaroslav Oui, très efficace, je suppose: D
aefxx

2
Sans index. Il convertit d'abord la valeur de la date en chaîne, puis correspond à cette chaîne. Dans MySQL, tout type de colonne peut être interrogé par LIKE. Mais cela fonctionnera quand même: D
Yaroslav

2
Des petites tables de jeux pour enfants?
Rob du

Il n'est pas nécessaire d'être fou de performance tout le temps, maintenant vous. Parfois, l'effort et le temps que vous consacrez à quelque chose pour le faire fonctionner quelques microsecondes plus rapidement ne font aucune différence, mais vous avez perdu ce temps.
Hristo Petev le

0

Voici une requête que j'utilise et elle renverra chaque enregistrement dans une période sous forme de somme.

Voici le code:

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

Cela répertorie chaque emp_nr et la somme des heures mensuelles qu'ils ont accumulées.


0

vous pouvez le faire en remplaçant $ q par ceci:

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

-1

Oui, cela fonctionne, mais cela ne renvoie qu'une seule ligne alors qu'il y a plusieurs lignes à récupérer en utilisant uniquement les colonnes sélectionnées. Comme SELECT Title, Date FROM mytable WHERE YEAR (Date) = 2017 AND MONTH (Date) = 09 renvoie une seule ligne.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.