Una parte de tu enrollo es que estás combinando bases de datos y programación para ahcer una tarea que la base de datos está capacitada para hacer mejor por sí sola...
Me explico:
Si lo que quieres es listar todo el contenido de tabla1, donde la fecha esté en un rango y los datos comprendidos en una lista de categorías, tienes dos formas:
1. Si quieres seguir usando el array, te recomiendo que los pases directamente como parámetro de consulta, de modo de poder usar la cláusula IN:
Código sql:
Ver originalSELECT *
FROM tabla1
WHERE fecha BETWEEN '2008-09-10' AND '2008-09-11'
AND categoria IN(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
donde "
1, 2, 3, 4, 5, 6, 7, 8, 9, 10" representaría el contenido del parámetro pasado al string y construido sobre la base del array. En este sentido, la idea es que pases TODOS LOS VALORES separados por comas como parte del string y ubicados dentro del paréntesis del IN().
Es muy eficiente y rápido.
Si además quisieras agrupar u ordenar el resultado, puedes hacer algo como esto:
Código sql:
Ver originalSELECT *
FROM tabla1
WHERE fecha BETWEEN '2008-09-10' AND '2008-09-11'
AND categoria IN(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
ORDER BY fecha, categoria;
Esto te devolvería el resultado ordenado por fecha y categoría, simplemente.
2. La otra opción es si deseas usar la totalidad de las categorías. Allí te conviene tener una tabla CATEGORIA y realizar la consulta directamente cruzando los resultados:
Código sql:
Ver originalSELECT *
FROM tabla1
WHERE fecha BETWEEN '2008-09-10' AND '2008-09-11'
AND categoria IN(SELECT categoria_id FROM categorias)
GROUP BY fecha, catedoria;
El resultado es en esencia idéntico, pero la diferencia (que mejora la cosa) es que si aumentas el numero de categorías de la tabla, no es necesario modificar el script de la consulta, porque los valores nuevos se incluyen dinámicamente.
Cualquiera de estos dos casos será más rápido que lo que actualmente estás haciendo, en esencia porque el método que estás usando realiza demasiadas consultas a la base... y precisamente lo que debes siempre tratar de evitar es que el motor de base de datos realice lecturas a disco. Mientras menos veces acceda al disco, mejor erá la performance.
Como agregado, un consejo que te dieron más arriba es cierto: Trata de evitar traer todos los campos
a menos que sea estrictamente necesario. El SELECT * ... es la forma más ineficiente y de peor performance en una consulta. Además: ¿para que traer 54 campos (supongamos) si en realidad voy a manipular y usar 7? No tiene sentido.
Tip final: Si quieres saber cómo se hace para calcular el costo en tiempo de una consulta, recuerda:
a) Los motores de bases de datos leen los registros por bloques (agrupan los registros en bloques de tamaño fijjo).
b) Los bloques son habitualmente de 64 kb.
c) Cada bloque es un acceso al disco (overhead de hardware) y cada acceso a disco es tiempo de microprocesador.
d) La longitud en bytes de un registro se debe usar para calcular cuántos regisrtos entran en un bloque. Ese resultado lo usas para dividir la cantidad de registros devueltos por una consulta, y que en MySQL lo puedes obtener usando el EXPLAIN. Una de las columnas expresa cuantos registros afecta cada parte de la consulta.
e) Ese cálculo te dirá cuántos accesos a disco usa una consulta.
Recuerda: Mientras menos accesos a d sico uses, más eficiente es la consulta.
Para reducirlos, hay muchas técnicas:
- Aumentar la selectividad de la consulta (escribirla de modo que devuelva la cantidad mas específica de registros).
- Crear índices no agrupados que cubran la selectividad del WHERE.
- Forzar el uso de diferentes índices para adecuar la consulta. Si los campos del SELECT están en el índice, entonces MySQL no lee la tabla (!).
- No poner demasiadas validaciones en el WHERE, no es optimizable.