Dudas de consulta SQL

Iniciado por Skeletron, 6 Diciembre 2009, 21:38 PM

0 Miembros y 1 Visitante están viendo este tema.

^Tifa^

#10
Hasta ahora es que mas o menos vengo a entender tu peticion  :P

Haz intentando con $row["tipo.id"] o $row["locales.tipo"] o sencillamente $row['id'] ya que total tipo en locales y id en tipo tienen el mismo valor.

PD: Tu consulta tiene un problemita de optimizacion chiquito  ;)  es super bueno que te funcione pero.... si haces esto:

CitarON l.tipo=t.id

Le estas diciendo al optimizador de mysql, buscame en todas las columnas donde ambos datos correspondan... si tienes 10,000 columnas antes de retornarte el resultado final que solicitas con el WHERE l.calle = "independencia" (Que por cierto calle no es un indice es un campo comun y corriente segun expusiste... esto hara la consulta aun mas lenta que si campo fuese indice). Podrias ya que sabes que haras tu busquedad con la direccion, crear un indice en el campo calle y buscar la manera para que esto

CitarON l.tipo=t.id

No busque en todas las columnas existentes... podrias intentar antes de esa ultima validacion con algo mas o menos asi:

Código (sql) [Seleccionar]
WHERE l.tipo = (select tipo from table where calle = "independencia" ) and t.id = l.tipo

recuerdate crearle un INDEX al campo calle para hacer la validacion anterior.  ;)   lo anterior solo funciona si cuando hagas el select tipo where calle = bla retorne 1 solo valor, si retonar mas de 1 valor tendras que hacer algo como:

Código (sql) [Seleccionar]
WHERE l.tipo IN(select tipo from tabla where calle = "independencia") and t.id IN( select tipo from tabla where calle = "independencia")

no lo he probado esto te lo digo a puro comentario, pero mas o menos deberia funcionar y asi tu consulta quedaria mas optimizada de lo que no esta actualmente.

^Tifa^

Lo que provoca el horario nocturno tarde, suenio y pocas horas para dormir....

Obvia todo lo anterior que postee, he probado la consulta en el optimizador de MySQL (Ya que la anterior no la probe)

Te basta con crear un indice sobre el campo calle para que filtre y optimize la consulta como es  ;)  por ende puedes conservar intacta tu consulta, sencillamente crea un indice extra al campo calle para que el rendimiento sea mayor.

Un saludo

Skeletron

Llego la hora de especificar:

No voy a hacer 1 solo tipo de búsqueda.. el usuario podra hacer 4 tipos de busqueda:
la tabla en realidad, no tiene una "DIRECCION" sino que tiene 2 campos: CALLE y NUMERO (numero, es el numero de la calle.. como por ejemplo: Independencia 710).
También podra buscar por TIPOS de locales, tambien podra por NOMBRE DE LOCAL, y por ultimo, por servicios ofrecidos (aunque, de ésto no les he hablado.. ya que SI O SI tengo que hacer 2 consultas sql)


Supongamos que estamos haciendo la busqueda por DIRECCION..
El usuario podrá ingresar 3 valores:
Calle, Numero "DESDE" y numero "HASTA".. para buscar todos los locales en la calle Independencia, desde la altura 300 al 1000 (supongamos)

Mi codigo es éste:

Código (php) [Seleccionar]

$res = mysql_query("SELECT l.*, t.* FROM locales l INNER JOIN tipos t ON l.tipo=t.id WHERE l.calle='Independencia' AND l.numero > '300' and l.numero < '1000'");
echo "Resultados:<br />";
while($row = mysql_fetch_array($res)){
echo "<hr /><br />Nombre del local: " . $row['nombre'] . ", Tipo: " . $row['tipo'] . ", Direccion: " . $row['calle'] . " " . $row['numero'];
}

(suponemos que donde puse el dato: INDEPEDNENCIA y 300 y 1000, ahí estarán tomados los valores desde las variables GET del la URL
Y los datos de mi base de datos son:

Citar
   TABLAS:
      mails:                           TABLA DE MAILS
         mail(varchar:35)               Los Mails de los registrantes
      locales:                        TABLA DE LOCALES
         id(int:4) (primaria)            Identificador
           nombre(varchar:50)               Nombre del Local
          tipo(int:2) (indice)            Identificador Tipo de Local
           calle(varchar:100)               Direccion del local
           numero(int:4)                  Direccion del local
          servicios(varchar:50)            Numeros de los Servicios prestados
           telefono(varchar:15)            Telefono del local
          votos (int:4)                  Total de votos recibidos
          total(int:5)                  Suma del total de los votos
           observacion(varchar:120)         Observaciones nuestras
       tipos:                           TABLA DE TIPOS DE LOCALES
          id(int:2) (primaria)            Identificador
           tipo(varchar:30)               Tipo de Locales: Delivery, Bar, etc
       servicios:                        TABLA DE SERVICIOS
          id(int:2) (primaria)            Identificador
           tipo(varchar:30)               Tipo de servicio: Gaseosas, Alcohol, Hospedaje, Delivery, etc
      opiniones:                        TABLA DE OPINIONES
          id(int:4) (indice)               Identificador
           texto(varchar:1000)               Texto de la opinion



La web que es?
La web tendrá todos los datos de todos los tipos de locales que hay en MI BARRIO de MI CIUDAD...
Por lo que la gente que quiera buscar que locales hay en X calle, podra hacerlo buscando por direccion..
Si quieren bsucar donde esta el local: "Don Juan el Pizzero" podran hacerlo bsucando por NOMBRE
Si quieren buscar donde venden Pizzas y Gaseosas, lo harán con otro metodo (el valor SERVICIOS dentro de LOCALES, tendrá separado por comas "," cada tipo de servicio que ofrece.. pero esos valores, no serán los servicios en SI, sino, los numeros de los servicios que tambien estan identificados en la tabla SERVICIOS.. sería LO MISMO que pasa en éste caso..)


Ahora bien.. Sabiendo que hay 4 tipos de COnsultas.. Donde me conviene poner los Index? yo lo puse en TIPO.. porque supongo que lo que mas se va a buscar es el "TIPO" de local.. porque la mayoria (supongo) buscará Deliverys... o tambien puede que busquen por servicios.. eso lo haré con una consulta que mire si dentro de SERVICIOS está el numero "4" (supongamos que 4 es: EMPANADAS, y el usuario buscaba empanadas)...

Bien.. Ahí esta toda la explicacion...

Tifa, vos me decis que haga:

SELECT l.*, t.* FROM locales l INNER JOIN tipos t ON l.tipo=t.id WHERE l.tipo IN(SELECT tipo FROM tabla WHERE calle = "independencia") AND t.id IN( SELECT tipo FROM tabla WHERE calle = "independencia")

La verdad, no logré ententer eso.. que se supone que hará?

Skeletron

#13
Y que mejor para que vallan imaginando, que ver la web..

:www.brodasoft.com.ar/NuevaCordoba

Dont by Evil..
Puede tener XSS por el momento, porque esta en desarrollo.. no sean malos :D no prueben maldades :D

^Tifa^

#14
CitarTifa, vos me decis que haga:

SELECT l.*, t.* FROM locales l INNER JOIN tipos t ON l.tipo=t.id WHERE l.tipo IN(SELECT tipo FROM tabla WHERE calle = "independencia") AND t.id IN( SELECT tipo FROM tabla WHERE calle = "independencia")

La verdad, no logré ententer eso.. que se supone que hará?

Optimizacion chico, optimizacion. Recuerda que los registros en tu tabla iran creciendo con el tiempo y si dejas la consulta como la tienes, con el tiempo lo que tardaba en devolverte en a lo mejor 0.03 segundos en un futuro (depende el crecimiento de datos) podra tardar 0.50 segundos la misma consulta .... y si crecen mas datos dentro de la tabla luego no sera 0.50 segundos sino hasta 2 minutos lol.. para retornarte una consulta.

Obvia todo lo que dije anteriormente y ya que haz dado mas detalles de tus tablas:

Código (sql) [Seleccionar]


CREATE INDEX INDICE ON locales(calle, numero);



Y a tu consulta:



"SELECT l.*, t.* FROM locales l INNER JOIN tipos t ON l.tipo=t.id WHERE l.calle='Independencia' AND l.numero > '300' and l.numero < '10000'


Yo si fuese tu (por optimizacion) lo modificase a :



SELECT l.*, t.* FROM locales l INNER JOIN tipos t ON l.tipo=t.id WHERE l.calle='Independencia' AND l.numero in('3000','100000');


Skeletron

#15
Perfecto!!!
Quedó así:


y el codigo php así:

Código (php) [Seleccionar]
$res = mysql_query("SELECT l.*, t.* FROM locales l INNER JOIN tipos t ON l.tipo=t.id WHERE l.calle='Independencia' AND l.numero in('3000','100000')");
echo "Resultados:<br />";
while($row = mysql_fetch_array($res)){
echo "<hr /><br />Nombre del local: " . $row['nombre'] . ", Tipo: " . $row['tipo'] . ", Direccion: " . $row['calle'] . " " . $row['numero'];
}


La imagen de la tabla: LOCALES

Y ningun otro INDICE ni nada??


PERO.. HAY PROBLEMAS:. No me devuelve nada..
Ejecuto ese codigo tambien en PHPMyAdmin, y TAMPOCO devuelve algo...
Recuerdo que lo que yo quiero, es devolver todos los locales que tengan un valor de "numero" entre 300 y 1000.. el "IN ('300', '1000')" funcionaría???


Que me dices de los INDICES en OPINIONES, TIPOS y SERVICIOS??? Ellas 3, tienen solo 2 columnas.. y utilizo SIEMPRE, solamente 1 columna.. ID... Le hago indice en las 3?
En las 3 tablas, "ID" es "PRIMARY"... funciona tambien como indice? o hace falta que ID sea PRIMARY y tambien agregarle un INDICE?

^Tifa^

CitarY ningun otro INDICE ni nada??

Dependera siempre y cuando vayas a hacer tu consulta SQL solicitando realizar una busquedad por una condicion mas, por ejemplo suponte que al where..and..and quieres agregarle otro campo mas:

where numero between(algo,algo) and votos = algo

Entonces el campo votos habria que crearle un indice, de lo contrario puedes dejar todo igual.

CitarPERO.. HAY PROBLEMAS:. No me devuelve nada..
Ejecuto ese codigo tambien en PHPMyAdmin, y TAMPOCO devuelve algo...
Recuerdo que lo que yo quiero, es devolver todos los locales que tengan un valor de "numero" entre 300 y 1000.. el "IN ('300', '1000')" funcionaría???

Si pero fijate en la consulta que estas guardando (Y que yo te coloque):

SELECT l.*, t.* FROM locales l INNER JOIN tipos t ON l.tipo=t.id WHERE l.calle='Independencia' AND l.numero in('3000','100000')

l.numero in('3000','100000')  no deberia ser para tu caso l.numero in('300','1000') ??? Porque entre 3000 y 100000 hay mucha diferencia de numeros delante de entre 300 y 1000.


Skeletron

#17
Estoy usando éste:
$res = mysql_query("SELECT l.*, t.* FROM locales l INNER JOIN tipos t ON l.tipo = t.id WHERE l.calle = 'Independencia' AND l.numero IN ('300','1000')");


Y juro que no devuelve nada.. entre 300 y 1000
Y los numerros del ejemplo, estan entre ese rango.. muy extraño...
Mira las imagenes que puse arriba... ahí podras ver los valors exactos de las entradas..

mira:

^Tifa^

Ups.... vas a molestarte mucho conmigo  :-[   :-[   :-[   :-[   :-[   :-[ 

sorry..  :-\

Era un poco tarde cuando te sugeri lo que te sugeri (estaba mas dormida que despierta), y ahora mirando la consulta es que me doy cuenta de mi fallo  :-\

Mira, no te devuelve nada cuando haces esto:

$res = mysql_query("SELECT l.*, t.* FROM locales l INNER JOIN tipos t ON l.tipo = t.id WHERE l.calle = 'Independencia' AND l.numero IN ('300','1000')");

Debido a que l.numero IN('300','1000') se le esta diciendo a la consulta retorname todas las filas donde el campo numero tenga 300 o 1000  :-[  perdona, se que lo que tu buscas es que los datos esten entre 300 y 10000 no que sean exclusivamente 300 y 1000...

Tu consulta estaba bien como estaba anteriormente (cuando utilizabas);

AND l.numero > '300' AND l.numero < '1000'

O puedes acortarlo con :

AND l.numero BETWEEN '300' AND '1000'

De antemano disculpame... no fue tu culpa.  ;)

Skeletron

No por favor.. nada de disculpas.. Tu me estas salvando la vida mas de 1 vez.. nada de pedir disculpas :D

Continuando con alguna que otra pregunta:

Hace un tiempo me dijeron que agregar mas de 1 o 2 indices, ya hacía mas retardada la consulta.. y que hay que saber colocarlos bien a ellos, porque sino juega en contra.. es verdad ello?

Otra consultita:
Un "PRIMARY", tambien funciona como INDICE?