Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   SQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=6)
-   -   Select registros master según nº de líneas de detalle (https://www.clubdelphi.com/foros/showthread.php?t=41827)

fidel 27-03-2007 01:52:33

Select registros master según nº de líneas de detalle
 
Hola.

Win XP
Delphi 7
FireBird 1.5 enlazado con IBX

Tengo una tabla Master llamada ALUMNOS con su detalle FALTAS de disciplina.

Quiero seleccionar los alumnos que tengan un numero determinado de faltas, comprendido entre dos números cogidos de dos Edits.

Por ej. que me liste todos los alumnos con un número de faltas comprendido entre 5 y 10.

No se como hacerlo.

¿ Alguna idea o sitio donde encontrar ayuda sobre esto ?

Muchas gracias.

Un saludo.

poliburro 27-03-2007 02:59:45

Código SQL [-]
       Select Maestro.CveAlumno, Count(*)
         From TablaMaestro As Maestro
    Left Join TablaFallas As Fallas
           On Maestro.CveAlumno = Fallas.CveAlumno
   Group By Maestro.CveAlumno
      Having Count(*) > 5 And
              Count(*) < 10

roman 27-03-2007 03:07:04

¿Qué no podemos ahorrarnos el join?

Código SQL [-]
select CveAlumno, count(CveAlumno)
from Fallas
group by CveAlumno
having count(CveAlumno) between 5 and 10

// Saludos

fidel 27-03-2007 19:37:57

Muchas gracias, Poliburro y Román, voy a probarlo.

Un saludo.

fidel 28-03-2007 00:49:53

Me da este error:

Token Unknown -line 2, char 15 As
Código SQL [-]
  DM.IBDSAlumnos.SelectSQL.Add('Select Maestro.CODIALUMNO, Count(*)');
  DM.IBDSAlumnos.SelectSQL.Add(' From ALUMNOS As Maestro');
  DM.IBDSAlumnos.SelectSQL.Add(' Left Join FALTAS As Faltas');
  DM.IBDSAlumnos.SelectSQL.Add(' On Maestro.CODIALUMNO = Faltas.CALUMNO');
  DM.IBDSAlumnos.SelectSQL.Add(' Group By Maestro.CODIALUMNO');
  DM.IBDSAlumnos.SelectSQL.Add(' Having Count(*) between :DESDE and :HASTA');

  DM.IBDSAlumnos.ParamByName('DESDE').AsInteger := StrToInt('0' + EDesde.Text);
  DM.IBDSAlumnos.ParamByName('HASTA').AsInteger := StrToInt('0' + EHasta.Text);
¿Qué está mal?

Gracias.

poliburro 28-03-2007 17:33:11

Cita:

Empezado por roman
¿Qué no podemos ahorrarnos el join?
Código SQL [-]
select CveAlumno, count(CveAlumno)
from Fallas
group by CveAlumno
having count(CveAlumno) between 5 and 10
// Saludos

Si nos lo ahorraramos que sucedería con aquellos alumnos del maestro que no tuvieran faltas? (Detalle de faltas)?. Pues estos no aparecerían. y el reporte sería erroneo, a menos que explicitamente quisieran solo a los que tienen faltas. :P

Prueba con esto amigo.

[delphi]

Código Delphi [-]
With DM.IBDSAlumnos Do
  Begin
    SelectSQL.Text := 
      '    Select Maestro.CODIALUMNO, Count(*) ' +
      '      From ALUMNOS As Maestro ' +
      ' Left Join FALTAS As Faltas   ' +
      '        On Maestro.CODIALUMNO = Faltas.CALUMNO ' + 
      '  Group By Maestro.CODIALUMNO ' +
      ' Having Count(*) between :DESDE and :HASTA';
    ParamByName('DESDE').AsInteger := StrToInt('0' + EDesde.Text);
    ParamByName('HASTA').AsInteger := StrToInt('0' + EHasta.Text);
  End;

Suerte

roman 28-03-2007 19:31:28

Cita:

Empezado por poliburro
Si nos lo ahorraramos que sucedería con aquellos alumnos del maestro que no tuvieran faltas?

Cita:

Empezado por fidel
Quiero seleccionar los alumnos que tengan un numero determinado de faltas, comprendido entre dos números

:p

Claro que tienes razón, pero entiendo de la pregunta original que sólo interesan alumnos con faltas. Pero ciertamente, si se trata de una especie de reporte general, el join es necesario.

// Saludos

fidel 28-03-2007 19:47:10

Hola:

Lo que me indicas es lo mismo que tengo pero puesto en vez de con add en varias líneas con Text en una sola línea, por lo que da el mismo error, en el As, solo que ahora está en la linea 1 Char 60 .

Lo he cambiado así
Código SQL [-]
  DM.IBDSAlumnos.SelectSQL.Add('Select ALUMNOS.CODIALUMNO, Count(*)');
  DM.IBDSAlumnos.SelectSQL.Add(' From ALUMNOS');
  DM.IBDSAlumnos.SelectSQL.Add(' Left Join FALTAS');
  DM.IBDSAlumnos.SelectSQL.Add(' On ALUMNOS.CODIALUMNO = FALTAS.CALUMNO');
  DM.IBDSAlumnos.SelectSQL.Add(' Group By ALUMNOS.CODIALUMNO');
  DM.IBDSAlumnos.SelectSQL.Add(' Having Count(*) between :DESDE and :HASTA');

  DM.IBDSAlumnos.ParamByName('DESDE').AsInteger := StrToInt('0' + EDesde.Text);
  DM.IBDSAlumnos.ParamByName('HASTA').AsInteger := StrToInt('0' + EHasta.Text);

  DM.IBDSAlumnos.Open;

y ahora pasa sin error pero al abrir la tabla alumnos me da
IBDSAlumnos: campo 'NOMBRE' no encontrado.

Si en el select le añado el campo NOMBRE (Select ALUMNOS.CODIALUMNO, ALUMNOS.NOMBRE, Count(*)) me da otro error en Group By:

Invalid expression in the select list (not contained in either an agregate function or the GROUP BY clause)

Un saludo.

poliburro 28-03-2007 19:56:16

Entonces pruebalo así
Código SQL [-]


 
With DM.IBDSAlumnos Do  Begin    
    SelectSQL.Text :=
      '    Select Maestro.CODIALUMNO, Count(*) ' +
      '      From ALUMNOS As Maestro ' +      ' Left Join FALTAS As Faltas   ' +
      '        On Maestro.CODIALUMNO = Faltas.CALUMNO ' +
      '  Group By Maestro.CODIALUMNO ' +
      ' Having Count(*) between ' + EDesde.Text + ' And ' + EHasta.Text;  
End;

roman 28-03-2007 20:08:06

A ver, primero que nada me permito insistir un poco en lo del join. Si se están buscando sólo alumnos con faltas, el join hará innecesariamente más lenta la consulta.

Por otra parte, el error del campo NOMBRE, no creo que venga de cómo está puesta la consulta puesto que no hay ninguna referencia a ese campo. Más parece que la componente IBDSAlumnos tiene asignado algún campo permanente que hace referencia a ese campo.

También recomiendo a Fidel escoger nombres más indicativos para los alias, por que eso de FROM ALUMNOS AS MAESTRO, el día de mañana le va a traer un dolor de cabeza cuando intente recordar por qué los alumnos pasan a ser maestros.

// Saludos

fidel 28-03-2007 20:22:07

Hola Poliburro:

Esto sigue siendo lo mismo y dando el mismo error:
error en el As de As Maestro

Código SQL [-]
With DM.IBDSAlumnos Do
  Begin
    SelectSQL.Text := ' Select Maestro.CODIALUMNO, Count(*) ' +
     ' From ALUMNOS As Maestro' +
     ' Left Join FALTAS As Faltas ' +
     ' On Maestro.CODIALUMNO = Faltas.CALUMNO ' +
     ' Group By Maestro.CODIALUMNO ' +
     ' Having Count(*) between ' + EDesde.Text + ' And ' + EHasta.Text;
  End;

Respecto a lo que dice Román, en la consulta puse: ".. alumnos con un determinado número de faltas .." y ponía que se cogen de dos edits en los culales se puede poner por ejemplo

Desde 0 hasta 0 .. para ver alumnos que no tienen faltas
desde 1 hasta 9 .. para ver alumnos que tienen faltas pero menos de 10
desde 10 hasta 9999 .. para ver alumnos que tienen más de 10 faltas

De todas formas lo que me indicas ¿en que tabla iría?, ¿en la tabla Faltas?

¿Algo así ?
Código SQL [-]
  DM.IBDSFaltas.SelectSQL.Add('select CALUMNO, count(CALUMNO)');
  DM.IBDSFaltas.SelectSQL.Add(' from FALTAS');
  DM.IBDSFaltas.SelectSQL.Add(' group by CALUMNO');
  DM.IBDSFaltas.SelectSQL.Add(' having count(CALUMNO) between :DESDE and :HASTA');

Ivanzinho 29-03-2007 13:18:42

Cita:

Empezado por fidel
Hola Poliburro:
Esto sigue siendo lo mismo y dando el mismo error:
error en el As de As Maestro

Borra el As y con eso creo que te debería funcionar

Un saúdo

poliburro 30-03-2007 00:19:44

Cita:

Empezado por fidel
Hola Poliburro:

Esto sigue siendo lo mismo y dando el mismo error:
error en el As de As Maestro



Respecto a lo que dice Román, en la consulta puse: ".. alumnos con un determinado número de faltas .." y ponía que se cogen de dos edits en los culales se puede poner por ejemplo

Desde 0 hasta 0 .. para ver alumnos que no tienen faltas
desde 1 hasta 9 .. para ver alumnos que tienen faltas pero menos de 10
desde 10 hasta 9999 .. para ver alumnos que tienen más de 10 faltas

Es lo mismo por que la consulta es la correcta, por que no la pruebas en tu cliente de FireBird y ya que verifiques que funciona correctamente la pasas a delphi?.

Necesitas el join entre tu maestro y tu detalle para poder obtener las faltas de TODOS los alumnos, pues si lo haces como román te menciona, nunca te aparecerína alumnos sin faltas (Desde 0 hasta 0 .. para ver alumnos que no tienen faltas).

d-hugo 09-04-2007 09:55:09

El problema que yo veo es que no se especifica lo que se está contando. Yo usaría esto:
Código SQL [-]
SELECT alumnos.codialumno, COUNT(faltas.calumno) AS numfaltas
  FROM alumnos
  LEFT JOIN faltas ON alumnos.codialumno=faltas.calumno
GROUP BY alumnos.codialumno
HAVING (COUNT(faltas.calumno) BETWEEN [:desde] AND [:hasta]);

fidel 09-04-2007 21:12:17

Con lo que me indicas, d-hugo, me da el error:

IBDSAlumnos: Campo 'NOMBRE' no encontrado.

Gracias.

roman 09-04-2007 21:34:46

Este error, como te comenté antes no puede deberse a la consulta. Revisa a qué tienes enlazado el IBDSAlumnos. Si no es lo del campo permanente, quizá algún dbedit que anteriormente hubiera hecho referencia a ese campo.

// Saludos

Lepe 09-04-2007 23:02:02

Cita:

Empezado por roman
[...]por que eso de FROM ALUMNOS AS MAESTRO, el día de mañana le va a traer un dolor de cabeza cuando intente recordar por qué los alumnos pasan a ser maestros.

... Es que precisamente el día de mañana, los alumnos serán maestros :D :p

OFFTOPIC: Perdón, no me he podido resistir:rolleyes:

d-hugo 10-04-2007 03:32:03

Roman tiene razón, fíjate que 'NOMBRE' no aparece por ninguna parte en la consulta. Algo tienes de más por alguna parte.


La franja horaria es GMT +2. Ahora son las 18:32:16.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi