Foro de elhacker.net

Programación => Bases de Datos => Mensaje iniciado por: flashkeyboard en 3 Mayo 2010, 20:06 pm



Título: Para programadores avanzados en mySQL
Publicado por: flashkeyboard en 3 Mayo 2010, 20:06 pm

ayuda

la informacion de la tabla para los ejemplos es la siguiente

CREATE TABLE `tabla_test` (
  `idtabla_test` int(10) unsigned NOT NULL auto_increment,
  `nombre` varchar(45) NOT NULL default '',
  `caso` varchar(45) NOT NULL default '',
  PRIMARY KEY  (`idtabla_test`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `tabla_test` VALUES ('1', 'CARLOS', 'A');
INSERT INTO `tabla_test` VALUES ('2', 'CARLOS', 'A');
INSERT INTO `tabla_test` VALUES ('3', 'JUAN', 'C');
INSERT INTO `tabla_test` VALUES ('4', 'JUAN', 'A');
INSERT INTO `tabla_test` VALUES ('5', 'CARLOS', 'C');
INSERT INTO `tabla_test` VALUES ('6', 'CARLOS', 'C');
INSERT INTO `tabla_test` VALUES ('7', 'JUAN', 'C');
INSERT INTO `tabla_test` VALUES ('8', 'CARLOS', 'C');
INSERT INTO `tabla_test` VALUES ('9', 'JUAN', 'A');
INSERT INTO `tabla_test` VALUES ('10', 'JUAN', 'A');
INSERT INTO `tabla_test` VALUES ('11', 'CARLOS', 'C');
INSERT INTO `tabla_test` VALUES ('12', 'JUAN', 'C');
INSERT INTO `tabla_test` VALUES ('13', 'JUAN', 'A');
INSERT INTO `tabla_test` VALUES ('14', 'CARLOS', 'C');


Tengo una tabla de 3 campos de esta forma

ID   NOMBRE   CASO

1   CARLOS   A
2   CARLOS   A
3   JUAN    C
4   JUAN           A
5   CARLOS   C
6   CARLOS   C
7   JUAN    C
8   CARLOS   C
9   JUAN    A
10   JUAN    A
11   CARLOS   C
12   JUAN    C
13   JUAN    A
14   CARLOS   C


QUE QUERY DEBO USAR PARA QUE ME DEVUELVA ESTE RESULSET


NOMBRE      CASOS_ABIERTOS      CASOS_CERRADOS

JUAN            4                        3

CARLOS         2                         5




EH INTENTADO DE TODO, PERO ES NOTABLE QUE MI NIVEL EN MYSQL NO ES MUY ALTO

UTILICE SUBQUERYS, COUNTS Y NADA


LO QUE TENGO ES LO SIGUIENTE

PERO ME DA ERROR

SELECT
nombre,
count(caso) as Abiertos,
(SELECT
count(caso)
FROM tabla_test t
where caso = 'C'
GROUP BY nombre) as Cerrados
FROM tabla_test t
where caso = 'A'
GROUP BY nombre


GRACIAS!  :-[


Título: Re: Para programadores avanzados en mySQL
Publicado por: ^Tifa^ en 5 Mayo 2010, 06:15 am
Ando con el tiempo encima lo siento.....

No podre expandirme pero....

En 1 sola consulta tu estructura (nisiquiera con un Self Join) lo veo factible... los motivos te los explico luego que ando rapidito...

Pero, hay formas de sacar lo que quieres, ya sea con un CURSORS de MySQL, ya sea con un UNION o ya sea creando otra Tabla en el motor MEMORY para que se resetee la data ya que esta en memoria volatil... y usar algo tipo:

Tabla:

Citar
mysql> create table Temporal(
    -> nombres char(20),     
    -> abiertos int,         
    -> cerrados int) engine = memory;

Y para llenarla:

Citar
mysql> insert into Temporal values((select nombre  from test where caso = 'A' group by(nombre) limit 1), (select count(caso) from test where caso = 'A' group by(nombre) limit 1), (select count(caso) from test where caso = 'C' group by(nombre) limit 1));

Tengo que usar LIMIT 1 porke si quieres insertar mas tendras que sacar la data primero en un bucle y ir insertandola ya que es la unica forma...

Luego te explico... que ando volando.


Título: Re: Para programadores avanzados en mySQL
Publicado por: alone-in-the-chat en 11 Mayo 2010, 21:39 pm
O.O

Tiempo sin postear por aqui de aburrido cogi tu post lo mire y como dice Tifa tienes esas maneras de hacer la cosa .

Pero cuando me entra curiosidad me pongo a trastear y vi que si la pude sacar.

Pueba con esto

Código
  1.  
  2. SELECT t.nombre , COUNT(*) AS Abierto , (SELECT COUNT(*) FROM tabla_test WHERE caso = 'C' AND nombre=t.nombre ) AS Cerrados
  3. FROM tabla_test t WHERE caso='A'
  4. GROUP BY nombre
  5.  
  6.  

Espero te sirva.


Saludos!!


Título: Re: Para programadores avanzados en mySQL
Publicado por: ^Tifa^ en 13 Mayo 2010, 04:19 am
Gracias alone-in-the-chat... ultimamente me ando quedando cortita de tiempo (a excepcion de los fines de semana). Y pues es dificil para mi, concentrarme en responder preguntas de esta indole cuando tengo el tiempo encima, y cosas pendientes por terminar en ese reducido tiempo  :xD  pero grax si el usuario vuelve a lo mejor le pueda servir.

Una cosa si debes llevar claro, tanto tu como el... cuidado con los COUNT all y los valores NULL

Besis  :-*


Título: Re: Para programadores avanzados en mySQL
Publicado por: doreymis en 1 Junio 2010, 17:09 pm
hola que tal.. tengo un problemita similar al de flashkeyboard..
se trata de que necesito que me devuelva el listado de la nomina junto con los dias laborados y los dias sancionados.

les dejo mi sentencia

Código:
select empleado.ci, empleado.nombre1, empleado.nombre2, empleado.apellido1,empleado.apellido2,
empleado.cargo, asistencia.quincena , count(asistencia.asistencia) as "dias laborados",

(select count(asistencia.sancion) as "sancion" from asistencia join empleado
where asistencia.ci = empleado.ci
and asistencia.sancion = true
and asistencia.quincena = "2da de Mayo" group by asistencia.ci) as "dias sancionados"

from empleado join asistencia
where asistencia.asistencia=true
and  asistencia.ci=empleado.ci
and asistencia.quincena="2da de Mayo" group by asistencia.ci


y este es el error que me genera:
Código:
Subquery returns more than 1 row.




Título: Re: Para programadores avanzados en mySQL
Publicado por: ^Tifa^ en 2 Junio 2010, 16:18 pm
Cuidado, cuidado, cuidado con los GROUP BY en una Subquery que no guarde el resultado en un arreglo  ;)

Código
  1. (SELECT COUNT(asistencia.sancion) AS "sancion" FROM asistencia JOIN empleado
  2. WHERE asistencia.ci = empleado.ci
  3. AND asistencia.sancion = TRUE
  4. AND asistencia.quincena = "2da de Mayo"[b] GROUP BY[/b] asistencia.ci) AS "dias sancionados"
  5.  
  6.  

En esa consulta se retornara mas de 1 registro, sin embargo como consulta independiente sola si funcionaria, pero como subconsulta NO al no ser claro esta que guardaras los registros retornados en un arreglo... algo mas o menos asi:

Código
  1. SELECT empleado.ci, empleado.nombre1, empleado.nombre2, empleado.apellido1,empleado.apellido2,
  2. empleado.cargo, asistencia.quincena , COUNT(asistencia.asistencia) AS "dias laborados" , campo IN
  3.  
  4. (SELECT COUNT(asistencia.sancion) AS "sancion" FROM asistencia JOIN empleado
  5. WHERE asistencia.ci = empleado.ci
  6. AND asistencia.sancion = TRUE
  7. AND asistencia.quincena = "2da de Mayo" GROUP BY asistencia.ci) AS "dias sancionados"
  8.  
  9. FROM empleado JOIN asistencia
  10. WHERE asistencia.asistencia=TRUE
  11. AND  asistencia.ci=empleado.ci
  12. AND asistencia.quincena="2da de Mayo" GROUP BY asistencia.ci
  13.  
  14.  

Pero lo anterior puede que no precisamente te retorne lo que andas solicitando en realidad, (deberia evaluar la estructura de las tablas existentes, los registros, y analizar y ejecutar tu consulta SQL que no lo he hecho  :xD )

Pero no puedes usar la clausula GROUP BY en una subquery donde no exista una especie de arreglo que capte dicho resultados, en tu caso como No existe un arreglo que capte y asumiendo que si usas IN no retorne lo que solicitas, pues tendras que obviar el GROUP BY de la subquery y unicamente usar campos con igualaciones constantes (digase  WHERE CAMPO = CAMPO AND CAMPO = CAMPO) y si tu tabla respeta la normalizacion, con campo = campo no debera retornar mas de 1 registro duplicado (que si retorna mas de un duplicado te pasara el mismo inconveniente) y tendras que filtrar la subquery usando algo como LIMIT por ejemplo o la clausula DISTINCT

Salu2


Título: Re: Para programadores avanzados en mySQL
Publicado por: doreymis en 2 Junio 2010, 17:53 pm
hola... sabes que de leer y leer buscar y buscar pude llegar a una solucion...
me hacia falta algo que filtrara la sentencia...

lo coloque de esta manera y me trajo exactamente los resultados que necesitaba:

select empleado.ci, empleado.nombre1, empleado.nombre2, empleado.apellido1,empleado.apellido2,
empleado.cargo, asistencia.quincena ,
count(asistencia.sancion)as "sancionados",
(select count(asistencia.asistencia)
from asistencia join empleado
where asistencia.ci = empleado.ci
and asistencia.asistencia = true
and asistencia.quincena = "2da de Mayo"
group by asistencia.ci having asistencia.ci = empleado.ci) as "laborados"
from asistencia join empleado
where asistencia.ci = empleado.ci
and asistencia.sancion = true
and asistencia.quincena = "2da de Mayo" group by asistencia.ci

les dejo mi solucion para quien pueda necesitarla....  ;-) ;-) ;-)

gracias..!!!  ;D


Título: Re: Para programadores avanzados en mySQL
Publicado por: nicknamex en 19 Julio 2010, 21:32 pm
Primeramente Muchas gracias por las anteriores entradas pues me sirvieron mucho mucho ;-).

Ahora quisiera saber si alguien sabe como formatear la salida de un SELECT para que quede así:
Registro1,Registro2,Registro3,Registro4
(... en un solo texto)
Actualmente lo hago con el PHP, pero creo que sería mejor hacerlo directamente con MySQL
Gracias de Antemano


Título: Re: Para programadores avanzados en mySQL
Publicado por: Shell Root en 19 Julio 2010, 22:19 pm
No entendí así?
Código
  1. mysql> SELECT -1 AS Num1, -2 AS Num2, -3 AS Num3, -4 AS Num4, -5 AS Num5;
  2.  
  3. +------+------+------+------+------+
  4. | Num1 | Num2 | Num3 | Num4 | Num5 |
  5. +------+------+------+------+------+
  6. |   -1 |   -2 |   -3 |   -4 |   -5 |
  7. +------+------+------+------+------+
  8.  
  9. 1 ROW IN SET (0.00 sec)

Entonces que dentro de un text, aparezca así:
Código
  1. sText = " -1, -2, -3, -4, -5 "

Es mejor hacerlo directamente desde PHP. Creo que es más fácil.


Título: Re: Para programadores avanzados en mySQL
Publicado por: nicknamex en 20 Julio 2010, 20:44 pm
Por ejemplo si tengo un típico:
Código:
SELECT Registro FROM Tabla WHERE id>30
y esas salidas quererlas colocar en una casilla de una consulta mayor
Código:
SELECT id, nombre, apellido, FuncionX(SELECT Registro FROM Tabla WHERE id>30)
Por ejemplo quisiera un salida así

idnombreapellidoRegistros
1 fulano detal registro1,registro2,registro5
2mengano pelli registro2,registro7
. Creo que lo que quiero es algo parecido a una consulta de referencias cruzadas, con tablas externas.
Gracias


Título: Re: Para programadores avanzados en mySQL
Publicado por: Shell Root en 20 Julio 2010, 20:51 pm
mmm creo que sería más fácil hacerlo desde PHP. Y con un GROUP_CONCAT() así:
Código
  1. mysql> SELECT group_concat(COLLATION_NAME) FROM COLLATIONS;
  2.  
  3. big5_chinese_ci,big5_bin,dec8_swedish_ci,dec8_bin,cp850_general_ci,cp850_bin,hp8_english_ci,hp8_bin,koi8r_general_ci,koi8r_bin,latin1_german1_ci,latin1_swedish_ci,latin1_danish_ci,latin1_german2_ci,latin1_bin,latin1_general_ci,latin1_general_cs,latin1_spanish_ci,latin2_czech_cs,latin2_general_ci,latin2_hungarian_ci,latin2_croatian_ci,latin2_bin,swe7_swedish_ci,swe7_bin,ascii_general_ci,ascii_bin,ujis_japanese_ci,ujis_bin,sjis_japanese_ci,sjis_bin,hebrew_general_ci,hebrew_bin,tis620_thai_ci,tis620_bin,euckr_korean_ci,euckr_bin,koi8u_general_ci,koi8u_bin,gb2312_chinese_ci,gb2312_bin,greek_general_ci,greek_bin,cp1250_general_ci,cp1250_czech_cs,cp1250_croatian_ci,cp1250_bin,cp1250_polish_ci,gbk_chinese_ci,gbk_bin,latin5_turkish_ci,latin5_bin,armscii8_general_ci,armscii8_bin,utf8_general_ci,utf8_bin,utf8_unicode_ci,utf8_icelandic_ci,utf8_latvian_ci,utf8_romanian_ci,utf8_slovenian_ci,utf8_polish_ci,utf8_estonian_ci,utf8_spanish_ci,utf8_swedish_ci,utf8_turkish_ci,utf8_czech_ci,utf8_danish_ci,utf8_lithuanian_ci,utf8_ |
  4.  
  5. 1 ROW IN SET, 1 warning (0.00 sec)
  6.  
  7. mysql>


Título: Re: Para programadores avanzados en mySQL
Publicado por: nicknamex en 23 Julio 2010, 01:35 am
Tienes razón Shell Root, he estado revisando GROUP_CONCAT() y parece ser la respuesta para todos mis problemas. En mi ejemplo sería:
Código:
SELECT id, nombre, apellido, GROUP_CONCAT(Registro)
FROM Tabla
WHERE id>30
GROUP BY id
y me sale lo que quiero ::). Gracias.