Sv Community El Salvador
Soporte y Tecnología => Programación => Base de Datos => Mensaje iniciado por: vlad en agosto 31, 2009, 04:57:12 pm
-
Pues resulta que tengo problemas en formular una query que al parecer estoy intentando crearla de una forma nada que ver. Total que ya me rendí y pues hasta cólera me da porque siento que es una query sencilla al final :D
Bien pues la cosa es que tengo una tabla asi:
grupo | | valor |
1 | | a |
1 | | b |
1 | | c |
2 | | g |
2 | | b |
2 | | f |
3 | | a |
3 | | b |
3 | | f |
3 | | z |
En este caso necesito encontrar los grupos que tengan exactamente todos los valores (ni mas ni menos), es decir: si busco los que tengan valor "b" me que NO devuelva los grupos 1, 2 y 3, si busco los que tengan "a" y "b" que NO me devuelva los grupos 1 y 3, tampoco si busco "a", "b", "c" y "d" que no me devuelva ningun grupo (ni el grupo 1 aunque este contenga "a", "b" y "c").
Cada grupo puede contener X numero de valores porque es para un tabla de flags que estoy haciendo y pues la verdad para el caso solo necesito que si busco por quienes tienen exactamente los valores "a", "b" y "c" que me devuelva el grupo 1.
Creo que podrá ser muy evidente pero en este caso ya no veo la solución xD
Cualquier consejo/ayuda/pista/recomendación será muy bien recibida y muy apreciada.
-
Ayuda?
-
tiene que ser a puro query? o tambien puede llevar programacion? se me ocurre hacer uso de sub querys
basandome en esto
Cada grupo puede contener X numero de valores porque es para un tabla de flags que estoy haciendo y pues la verdad para el caso solo necesito que si busco por quienes tienen exactamente los valores "a", "b" y "c" que me devuelva el grupo 1.
no se si te sirve algo asi
select DISTINCT grupo from tabla where valor in ('a', 'b', 'c')
-
Gracias, realmente mi meta es que funcione a como de lugar.
No he probado aun esa query que pusiste, pero me parece que siempre aceptaria al grupo aunque hubiera un valor "d" verdad?.
Como en ese caso siempre supongo que agarraría al grupo 1 aunque exista un valor "d". Voy a hacer la prueba mejor, gracias!.
-
pos no entiendo que queres retornar¿?
-
Algunos datos de ejemplo por si alguien quiere ayudarme:
create database test;
use test;
insert into tester(grupo,valor) values (1,'a'),(1,'b'),(1,'c'),(1,'d'),(2,'a'),(2,'b'),(2,'f'),(3,'a');
+-------+-------+
| grupo | valor |
+-------+-------+
| 1 | a |
| 1 | b |
| 1 | c |
| 1 | d |
| 2 | a |
| 2 | b |
| 2 | f |
| 3 | a |
+-------+-------+
Test sobre el codigo de realbo:
select DISTINCT grupo from tester where valor in ('a', 'b', 'c');
Resultado:
+-------+
| grupo |
+-------+
| 1 |
| 2 |
| 3 |
+-------+
Ahi no tuvo que haber devuelto ningun grupo :)
Gracias de igual forma por la atención de intentar!.
-
fijate que me equivoque creo que no te funcionaria te retornaria los demas grupos pero tengo una duda, en el caso que pusiste queres que sea todos los valores es decir a b c d, o puede ser cualquiera? mira y siempre te interesa que sea el grupo 1 el que retorne? no te importa evaluar los demas?
aun no capto muy bien en base al query que te puse proba
select DISTINCT grupo from tester where valor not in ('a', 'b', 'c');
-
pos no entiendo que queres retornar¿?
Necesito que me retorne los grupos que tengan exactamente el juego de valores que le indique.
Digamos que fueran pupuserias, que cada pupuseria tuviera ciertos tipos de pupusas, pero yo necesito conocer solo las que tengan exactamente el tipo de pupusas que quiero, ni menos, ni mas.
ej.:
Grupo | Especialidad
Pupuseria 1 | Queso
Pupuseria 1 | Chicharron
Pupuseria 2 | Frijol
Pupuseria 2 | Queso
digamos que quisiera saber cuales tienen exactamente de Frijol Y Queso (y si la Pupuseria 2 llegara a poner de Chicharron entonces ya no contaria).
Gracias!
-
Necesito que me retorne los grupos que tengan exactamente el juego de valores que le indique.
Digamos que fueran pupuserias, que cada pupuseria tuviera ciertos tipos de pupusas, pero yo necesito conocer solo las que tengan exactamente el tipo de pupusas que quiero, ni menos, ni mas.
ej.:
Grupo | Especialidad
Pupuseria 1 | Queso
Pupuseria 1 | Chicharron
Pupuseria 2 | Frijol
Pupuseria 2 | Queso
digamos que quisiera saber cuales tienen exactamente de Frijol Y Queso (y si la Pupuseria 2 llegara a poner de Chicharron entonces ya no contaria).
Gracias!
Creo que realbo te ha dado una buena salida..
fijate que me equivoque creo que no te funcionaria te retornaria los demas grupos pero tengo una duda, en el caso que pusiste queres que sea todos los valores es decir a b c d, o puede ser cualquiera? mira y siempre te interesa que sea el grupo 1 el que retorne? no te importa evaluar los demas?
aun no capto muy bien en base al query que te puse proba
select DISTINCT grupo from tester where valor not in ('a', 'b', 'c');
No se si ya probastes de esa manera??? :big_boss:
-
No se si ya probastes de esa manera??? :big_boss:
Si ya lo probe, pero ahi hubo una confusión con respecto a lo que se queria retornar :)
Gracias.
-
pos ta algo cañon, el clavo que tengo ahorita es con aquellos grupos que tienen solo un valor de los buscados, siempre me aparecen :p
-
Si ya lo probe, pero ahi hubo una confusión con respecto a lo que se queria retornar :)
Gracias.
Bueno mira proba esta consulta... yo la hice a si...
SELECT GRUPO FROM TESTER WHERE GRUPO NOT IN (SELECT GRUPO FROM TESTER WHERE VALOR NOT IN('a', 'b') GROUP BY GRUPO)
Esta consulta te daria como resultado
3
Si haces esta..
SELECT GRUPO FROM TESTER WHERE GRUPO NOT IN (SELECT GRUPO FROM TESTER WHERE VALOR NOT IN('b') GROUP BY GRUPO)
No te arrojaria resultados...
Proba y me contas si es eso lo que keres..! ;)
-
Gracias!.
Probe con este:
SELECT GRUPO FROM tester WHERE GRUPO NOT IN (SELECT GRUPO FROM tester WHERE VALOR NOT IN('a', 'b','c','d') GROUP BY grupo);
tendria que retornar solo el grupo 1 pero retorna 1 y 3, y retornaria tambien cualquiera que tuviera al menos 1 de los grupos en el "NOT IN" y ninguno "invalido" (osea, retornaria los que "casi" pertecen tambien) :(
No se si me equivoco?
-
Gracias!.
Probe con este:
SELECT GRUPO FROM tester WHERE GRUPO NOT IN (SELECT GRUPO FROM tester WHERE VALOR NOT IN('a', 'b','c','d') GROUP BY grupo);
tendria que retornar solo el grupo 1 pero retorna 1 y 3, y retornaria tambien cualquiera que tuviera al menos 1 de los grupos en el "NOT IN" y ninguno "invalido" (osea, retornaria los que "casi" pertecen tambien)
No se si me equivoco?
un problema parecido es el que tengo, creo que lo que pasa es que no han entendido lo que andas buscando, ya me lo imaginaba al principio, pero quede completamente seguro con el ejemplo de las pupusas XD
pd:
solo por curiosidad, no sabes si el maravilloso mysql puede trabajar con el tipo de datos array?¿ y si podes crearlos a partir de un resultado del query, porque esa puede ser una solucion...
-
un problema parecido es el que tengo, creo que lo que pasa es que no han entendido lo que andas buscando, ya me lo imaginaba al principio, pero quede completamente seguro con el ejemplo de las pupusas XD
pd:
solo por curiosidad, no sabes si el maravilloso mysql puede trabajar con el tipo de datos array?¿ y si podes crearlos a partir de un resultado del query, porque esa puede ser una solucion...
Si fueras tan amable de proponer tu solucion aunque sea en otra variante de SQL?, de ahí podría figurarme mejor si hay alguna forma parecida en MySQL :D
Es que creo que en MySQL Arrays nativo no hay, pero eso *creo* nada mas :(
-
creo que es algo asi como lo que te explique en el messenger pero programado
-
creo que es algo asi como lo que te explique en el messenger pero programado
Me imagino que si, como bien me decias, no parece haber forma de hacerlo con 1 simple query, pese a que parece ser algo tan básico/simple.
Lo acabo de poner en el foro de soporte de MySQL tambien, para no quedarnos con la duda:
http://forums.mysql.com/read.php?10,279053,279053#msg-279053 (http://forums.mysql.com/read.php?10,279053,279053#msg-279053)
-
Si fueras tan amable de proponer tu solucion aunque sea en otra variante de SQL?, de ahí podría figurarme mejor si hay alguna forma parecida en MySQL
el truco esta en "concatenar" todos los valores de la columna "valor"
yo he creado tu tabla ejemplo en postgres y ahí estuve haciendo pruebas, de entrada imagine la solución que aquí te planteo porque ya he tenido que hacer algo parecido a lo que buscas....
teniendo la siguiente tabla
grupo valor
1 a
1 b
1 c
1 d
2 a
2 b
2 f
3 a
yo en postgres hago el siguiente script
select grupo, array_agg(valor)
from test
group by grupo;
retorna:
1 {a,b,c,d}
2 {a}
3 {a,b,f}
-
Por eso siempre prefiero las entidad relacion que las entidad atributo propiedad :P , estas EAV son medio problematicas al escalar :P
SELECT grupo
FROM mitabla
WHERE mitabla.valor in ('a', 'b') AND mitabla.grupo IN (SELECT mitabla.grupo FROM mitabla GROUP BY grupo HAVING COUNT(*) =2)
GROUP BY mitabla.grupo
Por cierto la mayorita de personas solo lo hacen qu tenga los atributos que buscas, no que tenga exactamente los que buscas, se recorta un monton.
SELECT grupo
FROM mitabla
WHERE mitabla.valor in ('a', 'b')
GROUP BY mitabla.grupo
HAVING COUNT(DISTINCT mitabla.valor) = 2
-
yo tambien probe utilizando el having count=cantidad de valores ingresados, pero me tope con un error cuando hay otro grupo que tiene solamente dos valores y uno de ellos esta en el rango ingresado
ejemplo
grupo valor
1 a
1 b
1 c
2 a
2 z
3 a
3 f
-
yo sinceramente por query lo veo dificil para mi es mezcla de querys y programacion
-
Por eso siempre prefiero las entidad relacion que las entidad atributo propiedad :P , estas EAV son medio problematicas al escalar :P
SELECT grupo
FROM mitabla
WHERE mitabla.valor in ('a', 'b') AND mitabla.grupo IN (SELECT mitabla.grupo FROM mitabla GROUP BY grupo HAVING COUNT(*) =2)
GROUP BY mitabla.grupo
Por cierto la mayorita de personas solo lo hacen qu tenga los atributos que buscas, no que tenga exactamente los que buscas, se recorta un monton.
SELECT grupo
FROM mitabla
WHERE mitabla.valor in ('a', 'b')
GROUP BY mitabla.grupo
HAVING COUNT(DISTINCT mitabla.valor) = 2
yo tambien probe utilizando el having count=cantidad de valores ingresados, pero me tope con un error cuando hay otro grupo que tiene solamente dos valores y uno de ellos esta en el rango ingresado
ejemplo
grupo valor
1 a
1 b
1 c
2 a
2 z
3 a
3 f
Pequeño error que en el primero le borre la ultima parte
SELECT grupo
FROM mitabla
WHERE mitabla.valor in ('a', 'b', 'c') AND mitabla.grupo IN (SELECT mitabla.grupo FROM mitabla GROUP BY grupo HAVING COUNT(*) =3)
GROUP BY mitabla.grupo HAVING COUNT(DISTINCT mitabla.valor) = 3
SELECT grupo
FROM mitabla
WHERE mitabla.valor in ('a', 'z',) AND mitabla.grupo IN (SELECT mitabla.grupo FROM mitabla GROUP BY grupo HAVING COUNT(*) =2)
GROUP BY mitabla.grupo HAVING COUNT(DISTINCT mitabla.valor) = 2
SELECT grupo
FROM mitabla
WHERE mitabla.valor in ('a', 'f',) AND mitabla.grupo IN (SELECT mitabla.grupo FROM mitabla GROUP BY grupo HAVING COUNT(*) =2)
GROUP BY mitabla.grupo HAVING COUNT(DISTINCT mitabla.valor) = 2
Listo espero que hoy si funcione con todo :)
-
el truco esta en "concatenar" todos los valores de la columna "valor"
yo he creado tu tabla ejemplo en postgres y ahí estuve haciendo pruebas, de entrada imagine la solución que aquí te planteo porque ya he tenido que hacer algo parecido a lo que buscas....
teniendo la siguiente tabla
grupo valor
1 a
1 b
1 c
1 d
2 a
2 b
2 f
3 a
yo en postgres hago el siguiente script
select grupo, array_agg(valor)
from test
group by grupo;
retorna:
1 {a,b,c,d}
2 {a}
3 {a,b,f}
Muy interesante, eso vienen siendo el GROUP_CONCAT en MySQL:
mysql> select GROUP_CONCAT(valor) from tester group by grupo;
+---------------------+
| GROUP_CONCAT(valor) |
+---------------------+
| a,b,c,d |
| a,b,f |
| a |
+---------------------+
3 rows in set (0.08 sec)
Sería de ver como evaluar los resultados despues de eso :)
Por eso siempre prefiero las entidad relacion que las entidad atributo propiedad :P , estas EAV son medio problematicas al escalar :P
SELECT grupo
FROM mitabla
WHERE mitabla.valor in ('a', 'b') AND mitabla.grupo IN (SELECT mitabla.grupo FROM mitabla GROUP BY grupo HAVING COUNT(*) =2)
GROUP BY mitabla.grupo
Por cierto la mayorita de personas solo lo hacen qu tenga los atributos que buscas, no que tenga exactamente los que buscas, se recorta un monton.
SELECT grupo
FROM mitabla
WHERE mitabla.valor in ('a', 'b')
GROUP BY mitabla.grupo
HAVING COUNT(DISTINCT mitabla.valor) = 2
Hey gracias :drinks: buen truco lo de usar la cuenta para deducir los validos!, ya lo voy a probar.
Precalcular el valor de comparación del count no es ningun problema, aunque fuera bueno una funcion de MySQL que contara los argumentos, pero eso ya es hacer cosas de mas :phew:
Y pues la mayoria podra hacer otras cosas pero para el caso quisiera experimentar con filtrar los resultados en base a propiedades exactas :thumbsup: ya veremos como "escala" de bien o mal este asunto :P
Gracias voy a probar!.
yo tambien probe utilizando el having count=cantidad de valores ingresados, pero me tope con un error cuando hay otro grupo que tiene solamente dos valores y uno de ellos esta en el rango ingresado
ejemplo
grupo valor
1 a
1 b
1 c
2 a
2 z
3 a
3 f
Umm eso es cierto, pues si ahi buscaras por "a", "b" y "c" el count para el grupo 2 y 3 sería de "2" mientras que para el grupo 1 sería de "3" - estaría bien.
Pero si buscara por "a" y "z" el count seria siempre igual (grupo 2 y 3 sería de "2" mientras que para el grupo 1 sería de "3") pero mostraria tanto el grupo 3 como el 2 :\
Parece que le hayaste un bug a la tecnica de rdoggsv jeje
-
Se me olvido el ultimo conteo vlad, lo q si me gustaria agregar esq mejor uses una has propiedades para esta onda, las columnas siendo las propiedades :P
-
ya voy a hacer el cambio entonces =)
Solo por probar la ultima solucion tekun/rdoggsv:
create table mitabla (grupo varchar(10), valor varchar(10));
insert into mitabla (grupo,valor) VALUES ('1','a'),('1','b'),('1','c'),('2','a'),('2','z'),('3','a'),('3','f');
mysql> SELECT grupo FROM mitabla WHERE mitabla.valor in ('a', 'b', 'c') AND mitabla.grupo IN (SELECT mitabla.grupo FROM mitabla GROUP BY grupo HAVING COUNT(*) =3) GROUP BY mitabla.grupo HAVING COUNT(DISTINCT mitabla.valor) = 3;
+-------+
| grupo |
+-------+
| 1 |
+-------+
1 row in set (0.07 sec)
mysql> SELECT grupo FROM mitabla WHERE mitabla.valor in ('a', 'z') AND mitabla.grupo IN (SELECT mitabla.grupo FROM mitabla GROUP BY grupo HAVING COUNT(*) =2) GROUP BY mitabla.grupo HAVING COUNT(DISTINCT mitabla.valor) = 2;
+-------+
| grupo |
+-------+
| 2 |
+-------+
1 row in set (0.00 sec)
mysql> SELECT grupo FROM mitabla WHERE mitabla.valor in ('a', 'f') AND mitabla.grupo IN (SELECT mitabla.grupo FROM mitabla GROUP BY grupo HAVING COUNT(*) =2) GROUP BY mitabla.grupo HAVING COUNT(DISTINCT mitabla.valor) = 2;
+-------+
| grupo |
+-------+
| 3 |
+-------+
1 row in set (0.00 sec)
Parece que funciona bien =D, al menos quedo de aprendizaje jeje gracias a todos.
-
Muy interesante, eso vienen siendo el GROUP_CONCAT en MySQL:
mysql> select GROUP_CONCAT(valor) from tester group by grupo;
+---------------------+
| GROUP_CONCAT(valor) |
+---------------------+
| a,b,c,d |
| a,b,f |
| a |
+---------------------+
3 rows in set (0.08 sec)
apos aqui ta tu solucion
select GROUP_CONCAT(valor) from tester
where GROUP_CONCAT(valor) ='a,b'
group by grupo;
-
Se me olvido el ultimo conteo vlad, lo q si me gustaria agregar esq mejor uses una has propiedades para esta onda, las columnas siendo las propiedades :P
err.. recapitulando, ya me acorde porque lo habia hecho asi :rofl: ¿y si las propiedades son variables en cantidad?, digamos, quien sabe si de acá a mañana las propiedades crezcan :roll:, tendria que ir agregando mas columnas por cada propiedad y dejar en NULL todas las nuevas celdas para las filas filas que antes no tenian esas propiedades.
¿Aun asi te parece mejor?
apos aqui ta tu solucion
select GROUP_CONCAT(valor) from tester
where GROUP_CONCAT(valor) ='a,b'
group by grupo;
Hey si verdad, teniendo en cuenta que puedo ordenar valor y que puedo ordenar la entrada a comparar, solo haría unos cambios (el principal seria usar HAVING en lugar de WHERE para que sea valido ;):
mysql> select grupo from tester group by grupo having GROUP_CONCAT(valor ORDER BY valor ASC) ='a';
+-------+
| grupo |
+-------+
| 3 |
+-------+
1 row in set (0.00 sec)
Interesante solución a la que has llegado tekun!
-
Poniendolo asi:
mysql> explain select grupo from tester group by grupo having GROUP_CONCAT(valor ORDER BY valor ASC) ='a';
+----+-------------+--------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | tester | ALL | NULL | NULL | NULL | NULL | 8 | Using filesort |
+----+-------------+--------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)
mysql> explain SELECT grupo FROM mitabla WHERE mitabla.valor in ('a', 'f') AND mitabla.grupo IN (SELECT mitabla.grupo FROM mitabla GROUP BY grupo HAVING COUNT(*) =2) GROUP BY mitabla.grupo HAVING COUNT(DISTINCT mitabla.valor) = 2;
+----+--------------------+---------+------+---------------+------+---------+------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+---------+------+---------------+------+---------+------+------+---------------------------------+
| 1 | PRIMARY | mitabla | ALL | NULL | NULL | NULL | NULL | 7 | Using where; Using filesort |
| 2 | DEPENDENT SUBQUERY | mitabla | ALL | NULL | NULL | NULL | NULL | 7 | Using temporary; Using filesort |
+----+--------------------+---------+------+---------------+------+---------+------+------+---------------------------------+
2 rows in set (0.00 sec)
Pinta bastante bien el metodo del group_concat como solución (excluyendo los posibles problemas en el orden de las propiedades a buscar claro), algun comentario ?
-
mysql> explain select grupo from tester group by grupo having GROUP_CONCAT(valor ORDER BY valor ASC) ='a';
+----+-------------+--------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | tester | ALL | NULL | NULL | NULL | NULL | 8 | Using filesort |
+----+-------------+--------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)
No habría problema si los ordenas, tal como lo hiciste aca...
tal como lo dijiste al inicio, la solución era muy simple, el truco esta en dejar de programar en modo procedual... Y encontrar la manera de decirla a la máquina QUE debe hacer, no COMO hacerlo :)
-
Pues ya estuve probando tu metodo y pues la verdad esta bastante practico y me ha funcionado (siempre teniendo en cuenta que hay que ordenar tanto el grupo concatenado como los valores a probar de la misma forma).
Asi que ahorita he dejado opcional en el programa el metodo a utilizar y con el tiempo se verá cual resultó mejor :D