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?

DiegoP.
la source
2
Vous pouvez utiliser l'instruction
Ben Carey

Réponses:

208
SELECT * FROM projects WHERE YEAR(Date) = 2011 AND MONTH(Date) = 5
Rick Kuipers
la source
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.

ypercubeᵀᴹ
la source
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.

aefxx
la source
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;
Arjan
la source
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
Nazmulhaqued
la source
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.

mahant chintan
la source
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
PAULDAWG
la source
2

Vous pouvez faire comme ceci:

$q="SELECT * FROM projects WHERE Year(Date) = '$year' and Month(Date) = '$month'";
Andreas Helgegren
la source
1
Cela n'utilise pas non plus d'index
Thijs Riezebeek
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

Hristo Petev
la source
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.

Frank Casser
la source
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;
Symon265
la source
-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.

BLOGBIR
la source