Search for this same question & answers here and elsewhere by digging around the web, always finding negative comments about making a query within the bucle while
.
Some comments
To get additional results I must make queries within an bucle while
if or if, I have no other option in my little knowledge base, this is my contradiction towards me.
My question:
How can I get additional data without application performance issues?
Note: The query and the result are carried out as a test procedure, the results are shown without any error, what is of concern are the negative comments of making queries within a,
bucle while
all queries are based on relational content, but if not, , if it weren't relational data.
$stmt = $con->prepare("SELECT id_producto,producto FROM producto WHERE activo=? order by id_producto ASC limit 5");
$stmt->bind_param("i",$activo);
$activo = "1";
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows>0) {
$stmt->bind_result($id_producto, $producto);
while ($stmt->fetch()) {
echo "<h1>$producto</h1>";
//Comporbar cuantas personas compraron este producto
$stmtOrden = $con->prepare("SELECT * FROM orden WHERE id_producto=? AND estadodelpedido=?");
$stmtOrden->bind_param("is",$id_producto,$estadodelpedido);
$estadodelpedido = "pagado";
$stmtOrden->execute();
$stmtOrden->store_result();
$comprasdeesteproducto = $stmtOrden->num_rows;
$stmtOrden->close();
echo "este producto se compro $comprasdeesteproducto veces";
//Comprobar dato del anunciante del producto
$stmtads = $con->prepare("SELECT * FROM ads WHERE id_producto=?");
$stmtads->execute();
$stmtads->store_result();
if ($stmtads->num_rows>0) {
$stmtads->bind_result();
while ($stmtads->fetch()) {}
} else {}
//Para evitar un extenso código solo añado las consultas como ejemplo
//Comprobar la eficiencia del vendedor al entregar el producto al cliente
$stmtVendedorCliente = $con->prepare("SELECT * FROM vendedor WHERE id_producto=?");
$stmtVendedorCliente->execute();
$stmtVendedorCliente->store_result();
if ($stmtVendedorCliente->num_rows>0) {
$stmtVendedorCliente->bind_result();
while ($stmtVendedorCliente->fetch()) {}
} else {}
//Comprobar el país del producto
$stmtPais = $con->prepare("SELECT * FROM pais WHERE id_producto=?");
$stmtPais->execute();
$stmtPais->store_result();
if ($stmtPais->num_rows>0) {
$stmtPais->bind_result();
while ($stmtPais->fetch()) {}
} else {}
}
} else {
echo "No existen registros";
}
Structure of the tables:
-- phpMyAdmin SQL Dump
-- version 4.5.1
-- http://www.phpmyadmin.net
--
-- Servidor: 127.0.0.1
-- Tiempo de generación: 24-10-2017 a las 03:50:04
-- Versión del servidor: 10.1.19-MariaDB
-- Versión de PHP: 5.6.28
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Base de datos: `shopping`
--
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `ads`
--
CREATE TABLE `ads` (
`id_ads` int(11) NOT NULL,
`id_producto` int(11) NOT NULL,
`ads` varchar(100) COLLATE utf8_spanish_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;
--
-- Volcado de datos para la tabla `ads`
--
INSERT INTO `ads` (`id_ads`, `id_producto`, `ads`) VALUES
(1, 1, 'J.Doe'),
(2, 2, 'Dani'),
(3, 3, 'mel');
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `orden`
--
CREATE TABLE `orden` (
`id_orden` int(11) NOT NULL,
`id_producto` int(11) NOT NULL,
`estadodelpedido` varchar(50) COLLATE utf8_spanish_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;
--
-- Volcado de datos para la tabla `orden`
--
INSERT INTO `orden` (`id_orden`, `id_producto`, `estadodelpedido`) VALUES
(2, 1, 'pagado'),
(3, 1, 'pagado'),
(4, 1, 'pagado'),
(5, 2, 'pagado'),
(6, 2, 'pagado'),
(7, 3, 'pagado');
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `pais`
--
CREATE TABLE `pais` (
`id_pais` int(11) NOT NULL,
`id_producto` int(11) NOT NULL,
`pais` varchar(100) COLLATE utf8_spanish_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;
--
-- Volcado de datos para la tabla `pais`
--
INSERT INTO `pais` (`id_pais`, `id_producto`, `pais`) VALUES
(2, 1, 'Mexico'),
(3, 2, 'España'),
(5, 3, 'sweden');
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `producto`
--
CREATE TABLE `producto` (
`id_producto` int(11) NOT NULL,
`producto` varchar(255) COLLATE utf8_spanish_ci NOT NULL,
`activo` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;
--
-- Volcado de datos para la tabla `producto`
--
INSERT INTO `producto` (`id_producto`, `producto`, `activo`) VALUES
(1, 'Nike', 1),
(2, 'Adidad', 1),
(3, 'gel', 1);
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `vendedor`
--
CREATE TABLE `vendedor` (
`id_vendedor` int(11) NOT NULL,
`id_producto` int(11) NOT NULL,
`calidad_de_entrega` int(11) NOT NULL,
`id_usuario` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;
--
-- Volcado de datos para la tabla `vendedor`
--
INSERT INTO `vendedor` (`id_vendedor`, `id_producto`, `calidad_de_entrega`, `id_usuario`) VALUES
(1, 1, 4, 1),
(2, 2, 5, 2),
(3, 3, 3, 6);
--
-- Índices para tablas volcadas
--
--
-- Indices de la tabla `ads`
--
ALTER TABLE `ads`
ADD PRIMARY KEY (`id_ads`);
--
-- Indices de la tabla `orden`
--
ALTER TABLE `orden`
ADD PRIMARY KEY (`id_orden`);
--
-- Indices de la tabla `pais`
--
ALTER TABLE `pais`
ADD PRIMARY KEY (`id_pais`);
--
-- Indices de la tabla `producto`
--
ALTER TABLE `producto`
ADD PRIMARY KEY (`id_producto`);
--
-- Indices de la tabla `vendedor`
--
ALTER TABLE `vendedor`
ADD PRIMARY KEY (`id_vendedor`);
--
-- AUTO_INCREMENT de las tablas volcadas
--
--
-- AUTO_INCREMENT de la tabla `ads`
--
ALTER TABLE `ads`
MODIFY `id_ads` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
--
-- AUTO_INCREMENT de la tabla `orden`
--
ALTER TABLE `orden`
MODIFY `id_orden` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
--
-- AUTO_INCREMENT de la tabla `pais`
--
ALTER TABLE `pais`
MODIFY `id_pais` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
--
-- AUTO_INCREMENT de la tabla `producto`
--
ALTER TABLE `producto`
MODIFY `id_producto` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
--
-- AUTO_INCREMENT de la tabla `vendedor`
--
ALTER TABLE `vendedor`
MODIFY `id_vendedor` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
The result I get:
As you have already been told, your nested queries consume a lot of resources and memory.
Doing
INNER JOIN
this does not solve your problem since you would be stopping bringing products that do not have a country, seller or ads.In addition, when applying
LIMIT 5
it, all the results would be reduced to 5 and in case the cardinality between tables is not 1-1, the result would be incorrect.A possible solution would be to make a subquery of products , apply the
LIMIT 5
and with the result do aLEFT JOIN
later to know the number of purchases, group the results and make aCOUNT
with and obtain them.The problem with this is that you will get a single result set where the description of the products will be repeated according to the countries, ads, and sellers (if the cardinality is not 1-1). In that case,
while
we would validate printing its description once for each item as well as validating the vendors, countries and ads to print their corresponding ones according to each product.Since you don't describe what you do with the countries, ads, and vendors, I put the options but left them without code.
here the example:
To obtain additional data you could use
SQL JOINS
and thus associate data in the same statement.To better understand the logic of the statement in my example, I have put the full name of each table before the columns that you want to obtain from the Database, in this way you will know how to differentiate each data that you want to obtain from different tables associated with
JOINS
.Now to calculate the total of purchases you must add another
SELECT
and you could usecount
to calculate the total of purchases, since it only has to choose where itsID
is equal.In the
INNER JOIN
LEFT JOIN
simply compares the same oneid
that you use as an identifier and thus correctly choose the data.If we assume that there will always be a seller and a country of origin, there is enough with
INNER JOIN
.In the event that the delivery quality vote is not mandatory , that is, it could happen that there is no record, you use a
LEFT JOIN
, in this way, even though there is no record, it will execute the sentence in the same way.A possible example: