Agrupar registros por fechas

532 views
Skip to first unread message

Ruben Samudio

unread,
May 9, 2014, 7:11:40 PM5/9/14
to publice...@googlegroups.com
Buenos días tengo un problema no se como agrupar los datos de una consulta, así:
fecha            nombre
01-01-14    Juan Gomez
01-01-14    Alberto Mario
02-01-14   Diana Prieto
02-01-14   Luis Alberto
en  una nueva consulta asi
fecha                       Operarios
01-01-14   Juan Gomez,Alberto Mario 
01-01-14   Diana Prieto. Luis Alberto
Gracias por su ayuda

Ultraton500

unread,
May 9, 2014, 7:19:49 PM5/9/14
to publice...@googlegroups.com
Hola Rubén, se agrupan usando la cláusula GROUP BY.
Ten en cuanta que todas las columnas que están antes del GROUP BY deben estar también después (sin importar el orden).
Espero te sea de utilidad.

Saludos,
Javier.

Ruben Samudio

unread,
May 9, 2014, 7:33:37 PM5/9/14
to publice...@googlegroups.com
La verdad no he podido colocar todos los nombres agrupados por las fechas puesto que los nombres estan en una misma columna

WGWH

unread,
May 9, 2014, 8:40:01 PM5/9/14
to publice...@googlegroups.com
En SQL normal no conozco que eso se pueda hacer, tu quieres que se muestre por cada fila una sola fecha (el agrupador) y en la siguiente columna de la misma fila, (en tu caso un nombre)  un listado todos los nombres separados por coma, es algo extraño lo que que necesitas. Ya tomastes en cuenta la cantidad de registros que podrías mostrar de esa forma?

Lo que se acostrumbra es hacer un reporte que evite imprimir mas de una vez un dato repetido en tu caso la fecha y que vaya imprimiendo los otros datos que no se repiten en tu caso los nombre, pero irán imprimiendose uno abajo del otro en distintas filas.

De hecho si averiguas como hacer eso que pides, sería interezante que lo publiques.

Saludos

W. Wassmer

Víctor Hugo Espínola Domínguez

unread,
May 9, 2014, 9:07:48 PM5/9/14
to publice...@googlegroups.com
Hola Rubén

El concepto de convertir filas a columnas se conoce como  Cross-Tab y tablas Pivot. El VFP tiene un wizard que deberías probar.

Para Sql Server puedes leer el siguiente enlace: http://www.sqlservercentral.com/articles/Crosstab/65048/

Prueba el siguiente código

Select c1.Fecha, c1.nombre, Count(c1.Fecha) As NroFila ;
    FROM curFecNom c1 ;
    INNER Join curFecNom c2 ;
        ON c1.Fecha = c2.Fecha And c1.nombre >= c2.nombre ;
    GROUP By c1.Fecha, c1.nombre ;
    INTO Cursor curFecNomFil

Calculate Max(NroFila) To lnKntNom

lcSelect = "Select Fecha"

For lnI = 1 To lnKntNom
    TEXT TO lcSelect ADDITIVE TEXTMERGE NOSHOW PRETEXT 15

    , Max(Iif(NroFila =  <<TRANSFORM(lnI)>>, Nombre, Space(Len(Nombre)))) As Nombre<<TRANSFORM(lnI,"@RL 99 ")>>

    ENDTEXT
Endfor

TEXT TO lcSelect ADDITIVE TEXTMERGE NOSHOW PRETEXT 15

    FROM curFecNomFil
    GROUP By Fecha
    ORDER By Fecha
    INTO CURSOR curFecNomCol
ENDTEXT

&lcSelect

lcSelect = "Select Fecha, RTRIM(Nombre01) "

For lnI = 2 To lnKntNom
    TEXT TO lcSelect ADDITIVE TEXTMERGE NOSHOW PRETEXT 15

        + ", " + RTRIM(Nombre<<TRANSFORM(lnI,"@RL 99")>>)

    ENDTEXT
Endfor

TEXT TO lcSelect ADDITIVE TEXTMERGE NOSHOW PRETEXT 15

    FROM curFecNomCol
    ORDER By Fecha

ENDTEXT

&lcSelect

Return


En otro mensaje te enviaré otra solución más corta y probablemente más rápida.

Saludos,
Víctor.
Lambaré - Paraguay.

Víctor Hugo Espínola Domínguez

unread,
May 9, 2014, 9:13:37 PM5/9/14
to publice...@googlegroups.com
Hola Rubén

Lo prometido:

Select Fecha, Personas(Fecha) ;
    FROM curFecNom ;
    GROUP By Fecha

Function personas(tdFecha As Date) As String

    Local lcNombres As String
    Local Array laNombres[1]

    Select nombre ;
        FROM curFecNom c ;
        Where c.Fecha = tdFecha ;
        INTO Array laNombres
    lcNombres = ""
    For lnI = 1 To Alen(laNombres, 1)
        lcNombres = lcNombres + Iif(Empty(lcNombres), "", ", ") + Rtrim(laNombres[lnI])
    Endfor

    Return lcNombres
Endfunc

Saludos,
Víctor.
Lambaré - Paraguay.

Ultraton500

unread,
May 9, 2014, 9:39:35 PM5/9/14
to publice...@googlegroups.com
Perdón Rubén, interpreté mal tu planteo.
Es sencillo, lo que puedes hacer es:

1- Obtener un cursor con los registros ordenados por fecha.
2- Recorrerlo secuencialmente y por cada registro ir guardando en la variable_a la fecha y en la variable_b el valor de la variable_b + el nombre + una coma, esto mientras la fecha no cambie.
Cuando la fecha cambie:
   a) Eliminas la última coma (que estaría de mas).
   b) Haces un insert en cursor_a (previamente creado para ese fin) en donde guardas el contenido de la variable_a y el contenido de la variable_b en los campos fecha y nombres respectivamente.
   c) Limpias las variables.

Y listo! Tienes un cursor como querías.
(El campo de cursor_a en donde guardas los nombres separados por coma debería ser un campo memo).

Espero te sea de ayuda.

Saludos,
Javier.

mpulla

unread,
May 10, 2014, 12:24:06 PM5/10/14
to publice...@googlegroups.com
Hola Ruben.

Como te dicen con Sql de VFP no se puede.

Con Sql server hay varias formas mira este ejemplo con tus datos

Esto lo tengo para un reporte que me pidió un cliente.

Select vta_VtaC.iNumero,
       cItemName =
       CASE
         WHEN vta_VtaC.iAnulado = 1 THEN 'Anulado'
         ELSE
            STUFF(
                  ( Select
                          ', ' + CAst(CAst(Vta_vtaD.nCantidad As Int) As nVarchar(10)) + ' ' + rtrim(Vta_vtaD.cDescripcion)
                     From vta_VtaD
                      Where vta_VtaD.iVtaCId = Vta_VtaC.iVtaCId
                       Order By vta_VtaD.cDescripcion
                     For XML PATH('')
                    ), 1, 1, ''
                  )
      END
FROM vta_VtaC
 Where vta_VtaC.iCajMovCId = 121

Saludos.
Mauricio

Víctor Hugo Espínola Domínguez

unread,
May 11, 2014, 10:14:47 PM5/11/14
to publice...@googlegroups.com
Hola Javier

Creo que tu idea es la mejor en sencillez y rapidez de ejecución, en este caso por tratarse de un cursor VFP no se justifica una solución usando SQL.

El código:

Local ldFecha As Date, lcNombres As String

Create Cursor curPivot (Fecha D, Nombres V(250))

lcNombres = ""
Select curFecNom
Scan
    ldFecha = curFecNom.Fecha
    Do While curFecNom.Fecha = ldFecha
        lcNombres = lcNombres + Rtrim(curFecNom.nombre) + ", "
        Skip 1
    Enddo
    Insert Into curPivot Values (ldFecha, Left(lcNombres, Len(lcNombres) - 2))
    lcNombres = Rtrim(curFecNom.nombre) + ", "
Endscan


Saludos,
Víctor.
Lambaré - Paraguay.

Víctor Hugo Espínola Domínguez

unread,
May 11, 2014, 11:28:54 PM5/11/14
to publice...@googlegroups.com
Hola

El código anterior falla si el último grupo costa de 1 solo registro, a continuación el código corregido:

Local ldFecha As Date, lcNombres As String

Create Cursor curPivot (Fecha D, Nombres V(250))

Select curFecNom
Scan
    lcNombres = ""

    ldFecha = curFecNom.Fecha
    Do While curFecNom.Fecha = ldFecha
        lcNombres = lcNombres + Rtrim(curFecNom.nombre) + ", "
        Skip 1
    Enddo
    Insert Into curPivot Values (ldFecha, Left(lcNombres, Len(lcNombres) - 2))
    Skip -1
Endscan

El mismo algoritmo usando SCAN anidados:

Local ldFecha As Date, lcNombres As String

Create Cursor curPivot (Fecha D, Nombres V(250))

Select curFecNom
Scan
    lcNombres = ""
    ldFecha   = curFecNom.Fecha
    Scan While curFecNom.Fecha = m.ldFecha
        lcNombres = m.lcNombres + Rtrim(curFecNom.nombre) + ", "
    Endscan
    Insert Into curPivot ;
        Values (m.ldFecha, Left(m.lcNombres, Len(m.lcNombres) - 2 ))
    Skip -1
    Loop
Endscan

Y por último, con DO WHILE anidados:

Local ldFecha As Date, lcNombres As String

Create Cursor curPivot (Fecha D, Nombres V(250))

Select curFecNom
Go Top
lcNombres = ""
ldFecha   = curFecNom.Fecha
Do While Not Eof()

    Do While curFecNom.Fecha = ldFecha
        lcNombres = lcNombres + Rtrim(curFecNom.nombre) + ", "
        Skip 1
    Enddo
    Insert Into curPivot Values (ldFecha, Left(lcNombres, Len(lcNombres) - 2))
    lcNombres = ""
    ldFecha   = curFecNom.Fecha
Enddo

Noten que aquí no es necesario el SKIP -1, es probable que éste sea el codigo más rápido.


Saludos,
Víctor.
Lambaré - Paraguay.

Carlos Miguel FARIAS

unread,
May 12, 2014, 6:04:17 AM5/12/14
to Grupo Fox

Por qué usan un do while dentro de un scan? No es la misma tabla?

Luis Maria Guayan

unread,
May 12, 2014, 9:25:13 AM5/12/14
to publice...@googlegroups.com
Para generar tablas cruzadas en VFP nada mejor ni mas rápido que FastXTab (by Alexander Gorovlev) que lo puedes descargar de: http://www.universalthread.com/ViewPageNewDownload.aspx?ID=9944

Hay una version de FastXTab Extendida (by Jun Tangunan) en: http://sandstorm36.blogspot.com.ar/2011/11/extending-fastxtab-cross-tab.html



Luis María Guayán
Tucumán, Argentina
_________________________
http://www.PortalFox.com
Nada corre como un zorro
_________________________

Víctor Hugo Espínola Domínguez

unread,
May 12, 2014, 6:35:00 PM5/12/14
to publice...@googlegroups.com
@Carlos
Debido a que a menudo se consulta sobre este tema de convetir filas en columnas  y como estaba enfrascado en el scratching balls at two hands, se me antojó mostrar varias soluciones del problema, con SQL, funciones, ciclos SCAN y WHILE anidados y mezclados, etc...

Ahí va otro con un solo SCAN:


Local ldFecha As Date, lcNombres As String

Create Cursor curPivot (Fecha D, Nombres V(250))

lcNombres = ""
Select curFecNom
Go Top
lcNombres = ""
ldFecha   = curFecNom.Fecha

Scan
    If curFecNom.Fecha = ldFecha
        lcNombres = lcNombres + Iif(Empty(lcNombres), "", ", ") + Rtrim(curFecNom.nombre)
    Else
        Insert Into curPivot Values (ldFecha, lcNombres)
        ldFecha   = curFecNom.Fecha
        lcNombres = Rtrim(curFecNom.nombre)
    Endif
Endscan
Insert Into curPivot Values (ldFecha, lcNombres)

Select curPivot

@Mauricio
Muy buena la página http://sqlfiddle.com/, altamente recomendable. Gracias por el enlace.

@Luís María
FastXtab requiere al menos 3 campos :-(

Saludos,
Víctor.
Lambaré - Paraguay.

Ruben Samudio

unread,
May 21, 2014, 4:58:48 PM5/21/14
to publice...@googlegroups.com
Víctor muchas gracias funciona super gracias por tu ayuda....
Gracias a todos
Reply all
Reply to author
Forward
0 new messages