En ocasiones necesitamos hacer consultas o queries en MySQL con PHP usando fechas. Por ejemplo, consultar las ventas de hoy, o las ventas del mes.
También puede que necesitemos consultar con fechas en un rango, ya sea un año, de hoy, de unas horas, etcétera.
Por ello es que vengo a mostrar hoy cómo hacer consultas con fechas en MySQL usando date y strtotime.
Consultar con fechas en MySQL y PHP
Tomemos un ejemplo sencillo de ventas en donde tenemos una tabla de ventas que tiene la fecha y hora en la que la misma fue realizada. Al consultar todos los datos se ve así:
MariaDB [ventas]> select * from ventas;
+----+------------+---------------------+---------+-------+-----------+--------+
| id | idPaciente | fecha | total | vista | idUsuario | estado |
+----+------------+---------------------+---------+-------+-----------+--------+
| 1 | 2 | 2019-09-18 13:34:03 | 450.00 | 0 | 0 | 0 |
| 2 | 1 | 2019-09-18 13:34:47 | 450.00 | 0 | 2 | 2 |
| 3 | 1 | 2019-09-18 13:35:16 | 450.00 | 0 | 2 | 1 |
| 4 | 1 | 2019-10-17 13:56:03 | 1050.00 | 0 | 0 | 1 |
| 5 | 1 | 2019-10-18 20:49:32 | 450.00 | 0 | 0 | 1 |
| 6 | 1 | 2019-10-18 21:46:00 | 450.00 | 0 | 2 | 1 |
| 7 | 1 | 2019-10-18 21:49:59 | 450.00 | 0 | 2 | 2 |
| 8 | 1 | 2019-10-22 08:51:21 | 450.00 | 0 | 2 | 1 |
| 9 | 1 | 2019-10-22 09:04:24 | 900.00 | 0 | 2 | 1 |
| 10 | 1 | 2019-10-22 09:07:56 | 1350.00 | 0 | 2 | 1 |
| 11 | 1 | 2019-10-22 09:08:15 | 450.00 | 0 | 2 | 1 |
| 12 | 1 | 2019-10-22 09:08:55 | 450.00 | 0 | 2 | 1 |
| 13 | 1 | 2019-10-23 19:39:58 | 1350.00 | 0 | 5 | 1 |
| 14 | 1 | 2019-10-23 19:45:37 | 1350.00 | 0 | 5 | 1 |
| 15 | 12 | 2019-11-06 18:30:35 | 450.00 | 0 | 2 | 2 |
| 16 | 9 | 2019-11-06 19:05:39 | 750.00 | 0 | 2 | 2 |
| 17 | 1 | 2019-11-06 19:09:54 | 900.00 | 0 | 2 | 2 |
+----+------------+---------------------+---------+-------+-----------+--------+
17 rows in set (0.00 sec)
Ahora veremos cómo consultar con determinadas fechas. Veamos el ejemplo para consultar las ventas del día 6 de noviembre del 2019.
Usar PHP para las fechas
Lo único que necesitamos son dos fechas: la del inicio y la del fin. La de inicio la proporciona el usuario o nosotros tomamos la fecha de hoy con:
$fecha = date("Y-m-d") . " 00:00:00";
Así tenemos la fecha de medianoche del inicio. Algo como 2019-11-06 00:00:00
Ahora el “problema” radica en el día siguiente, pues debemos consultar todas las del día, sin pasarnos y sin que nos falte (incluso si una venta se hizo a las 23:59)
Para ello, usamos strtotime
y obtenemos la fecha del siguiente día, así:
<?php
$fecha = date("Y-m-d") . " 00:00:00";
$diaSiguienteMedianoche = date("Y-m-d", strtotime("+1 day", strtotime($fecha))) . " 00:00:00";
echo $fecha; # 2019-11-06 00:00:00
echo $diaSiguienteMedianoche; # 2019-11-07 00:00:00
La magia para sumar fechas es usar strtotime
y +1 day
tomando como fecha para los cálculos la fecha de inicio.
Ahora que ya tenemos ambas fechas podemos hacer la consulta así (fíjate que primero es >=
y después es <
):
select * from ventas where fecha >= '2019-11-06 00:00:00' and fecha < '2019-11-07 00:00:00';
De modo que tome todas las fechas de hoy pero cuya fecha no sea mayor ni igual a mañana. Como las fechas se toman como cadena, el orden será respetado.
Con la siguiente salida:
MariaDB [ventas]> select * from ventas where fecha >= '2019-11-06 00:00:00' and fecha < '2019-11-07 00:00:00';
+----+------------+---------------------+--------+-------+-----------+--------+
| id | idPaciente | fecha | total | vista | idUsuario | estado |
+----+------------+---------------------+--------+-------+-----------+--------+
| 15 | 12 | 2019-11-06 18:30:35 | 450.00 | 0 | 2 | 2 |
| 16 | 9 | 2019-11-06 19:05:39 | 750.00 | 0 | 2 | 2 |
| 17 | 1 | 2019-11-06 19:09:54 | 900.00 | 0 | 2 | 2 |
+----+------------+---------------------+--------+-------+-----------+--------+
3 rows in set (0.00 sec)
Poniendo todo junto
Así que si usamos PDO con una conexión así:
<?php
$contraseña = "";
$usuario = "root";
$nombre_base_de_datos = "ventas";
try {
$base_de_datos = new PDO('mysql:host=localhost;dbname=' . $nombre_base_de_datos, $usuario, $contraseña);
$base_de_datos->query("set names utf8;");
$base_de_datos->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
$base_de_datos->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$base_de_datos->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
return $base_de_datos;
} catch (Exception $e) {
echo "Ocurrió algo con la base de datos: " . $e->getMessage();
}
?>
La consulta quedaría algo así:
<?php
include_once "base_de_datos.php";
$fecha = date("Y-m-d") . " 00:00:00";
$diaSiguienteMedianoche = date("Y-m-d", strtotime("+1 day", strtotime($fecha))) . " 00:00:00";
$consulta = "select * from ventas where fecha >= ? and fecha < ?";
$sentencia = $base_de_datos->prepare($consulta);
$sentencia->execute([$fecha, $diaSiguienteMedianoche]);
$ventas = $sentencia->fetchAll(PDO::FETCH_OBJ);
De esa manera evitamos inyecciones SQL y hacemos una consulta por fecha. Con este enfoque podríamos tomar meses, días, años, etcétera.