Concatenar campo

Tengo una base de datos llamada "pintura en general" la cual se compone de:
3 tablas:
"empleados" (idempleado, nombreempleado, apellido1, apellido2, dni, ss, horas, jornadas, nomina, activo)
"partes" (idparte, idempleado, diapresentacion,¿en plazo?, preciohora, preciojornada, ennomina, observaciones)
"detalle" (idetalle, idparte, fecha, descripcion, jornada, extras, extras-no, descuentos, a/c,atrasos, vacaciones)
1 consulta:
"horas extraordinarias" (varios campos de las 3 tablas)
3 formularios:
"empl_empleados"
"empl_partes"
"empl_detalle"
1 informe:
"pago mensual"
La cuestión es que el informe, el cual está basado en la consulta, me arroja los datos referidos a las horas extras, jornada de trabajo, pagos a cuenta, etc... Que han realizado los trabajadores en un mes determinado y durante el cual se han presentado diferentes partes. Todo ello agrupado por trabajador.
Todo va correcto en el cálculo en los distintos campos que componen el informe, me suma correctamente todas las horas extras realizadas durante el mes, los atrasos, los descuentos, las extras no computadas, es decir todos los campos numéricos, y me los totaliza en un campo individual en el informe.
El problema lo tengo con el campo "observaciones" de la tabla "partes". Este es un campo tipo memo el cual refleja las posibles incidencias que pueda conllevar cada uno de los partes presentados por cada trabajador. Al emitir el referido informe como he comentado anteriormente todos los demás campos me los agrupa correctamente pero este al tratarse de campo memo no lo puede sumar (agrupar) en uno sólo, por lo que me muestra el conjunto de los demás campos todos desagrupados tantas veces como número de "observaciones" (es decir partes) haya.
Por tanto lo que quiero es que al abrir el informe, ese campo "observaciones" de los diferentes registros, que correspondan según la consulta en la que está basado, quede concatenado en un único campo en el informe.
No se si me he expresado correctamente para que lo puedas entender.
Si quieres te podría enviar la bd para que vieras exactamente lo que ocurre y así te fuera más sencillo comprenderlo.
Mi e-mail es: [email protected]
Respuesta
-1
Te cuento: en la consulta que utilizas como origen de datos para el informe tendrías que agregar un campo que sería algo así:
TodasObservaciones:[empleados]!Observaciones & " - " & [detalle]!Observaciones & " - " & [partes]!Observaciones
después simplemente haces referencia al campo "TodasObservaciones" en el informe
Espero haberte entendido. Slds
Hola, el caso es que el campo "observaciones" pertenece tan sólo a la tabla partes, y en la consulta a la que me refiero lo que hace es llamar a barrios registros de la tabla partes en cada uno de los cuales hay un campo observaciones, unas veces como cadena vacía y otras con su correspondientes texto.
No obstante como te dije en la primera consulta si quieres te envío la BD y la ves.
Gracias
El problema es que no termino de entender bien lo que quieres hacer.
-¿Qué salga UN campo con todas las observaciones (con la suma de todas las observaciones que hay en tabla partes)?
Tendría que entender bien el problema primero. Perdón por mi torpeza.
Hola, no sabría que más decirte para explicarlo, creo que la única manera de verlo sería en la propia BD, por eso ofrecía mi e-mail en el primer mensaje para si os la podía hacer llegar. Es la mejor manera de comprenderlo.
De todas formas muchas gracias.

3 respuestas más de otros expertos

Respuesta
Si queda claro, solo que necesitaría saber que BBDD tienes porque tienes varias soluciones.
Aun así yo te pongo lo que haría si fuera en SQL2005.
Imaginemos que tenemos una tabla con dos campos: IdEmpleados (entero) y Texto (nvarchar(50)). Y queremos concatenar el Texto de todos aquellos que compartan un IDEmpleados. Haríamos pues:
declare @empleado as int
Declare @txt as nvarchar(50)
Declare @txtConcatenado as nVarChar(8000)
Declare cursor1 as cursor
for   select IdEmpleado from tabla
open cursor1
fecth next from cursor1 into @empleado
while @@fecth_status = 0
begin
    set @txtConcatenado = ' '
    declare cursor2 as cursor for select Texto from tabla where IdEmpleado = @empleado
    open cursor2
       fecth next from cursor2 into @txt
       while @@fecth_status = 0
       begin
          set @txtConcatenado = @txtConcatenado + @txt
          fetch next @cursor2 into @txt
       end
    close cursor2
    deallocate cursor2
    print @txtConcatenado -- O lo que quieras hacer guardar o lo que quieras
    fecth next @cursor1 into @empleado
end
close cursor1
deallocate cursor1
Ten en cuenta que esta función también se puede hacer en Access, Oracle, MySql... La filosofía de funcionamiento es la misma pero se escribiría diferente.
Hola mristol, y gracias.
Te comento que la base de datos que estoy utilizando es en access y que el código vba que he utilizado en alguna ocasión ha sido muy muy básico, por tanto si fueras tan amable de explicarme exactamente como colocar el código y más exactamente dónde y cómo tendría que llamarlo para que me lo ejecutara al correr el informe.
Muchas gracias por tu atención.
A ver tratándose de access deberías de hacer la programación dentro del VB del access. O sea dentro del formulario poner una función de este tipo:
Dim RS1 As Recordset
Dim RS2 As Recordset
Dim strSQL As String
Dim txt As String
Dim TxtConcatenado As String
strSQL = "select distinct IdEmpleado from Tabla"
set RS1 = CurrentDb().OpenRecordset(strSQL)
RS1.MoveFirst
Empleado = RS1!IdEmpleado
while (No haya acabado) then (
   strSQL = "select distinct Texto from Tabla where IdEmpleado = "+Empleado
    set RS2 = CurrentDb().OpenRecordser(strSQL)
    RS2.MoveFirst
   while (no haya acabado) then (
        Sacar datos e ir concatando dentro de TxtConcatenar
       RS2. MoveNext
        )
    RS2. Close
    RS1. MoveNext
    )
DoCmd.RunSQL "INSERT INTO NuevaTabla select '"+Empleado+"' as IdEmpleado, '"+TxtConcatenado+"' as Concatenado"
RS1. Close
Espero que te sirva deberás mirar alguna cosa que no recuerdo como por ejemplo el finalizador del Recordset que ahora no me viene a la memoria.
Respuesta
Necesito que me envíes la consulta para poder analizarla de mejor manera.
A priori te puedo indicar que lo más probable es que necesites utilizar subconsultas para traer todas las observaciones en filas. Posteriormente, tendremos que utilizar un pivot para convertir estas filas en columnas. Finalmente, estas columnas las podremos concatenar convirtiendo el campo tipo memo en strings.
Hola y gracias por tu atención.
¿Cómo te puedo enviar la BD?
Saludos
NO... si solo necesito que me envíes la consulta que te está causando el problema.
Hola, la consulta contiene los campos siguientes:
Empleado: [nombreempleado] & " " & [apellido1] & " " & [apellido2]
Agrupar por
TotalHoras:suma([horas]-[descuentos])
Expresión
?/extra
Detalle
Agrupar por
PagoExtras: [TotalHoras]*[?/extra]
Expresión
TotalJornadas:(suma([jornada]))/8
Expresión
?/jornada
Detalle
Agrupar por
Pagojornada:[Totaljornadas]*[?/jornada]
Expresión
TotalAPagar:[Pagoextras]+[Pagojornada]
Expresión
Observaciones
Partes
Agrupar por
Mes([fecha])
Donde
Como "*" & [NUMERO DEL MES]
Año([fecha])
Donde
Como "*" & [AÑO]
Ok. Con esto me estas diciendo que la base la tienes en Access...
¿Dónde sacaste esta información, puedes ver la "Vista SQL"? Porque Access tiene la "Vista Diseño" (que me imagino de donde sacaste esta información), la "Vista de Datos" (donde se muestran los datos) y la "Vista SQL" (donde se vé la consulta SQL).
Si no me equivoco, en la misma "Vista Diseño" aparece un botoncito que dice SQL... la consulta debería ser algo así:
SELECT [Empleado].[nombreempleado] & " " & [Empleado].[apellido1] ......
FROM [....]
WHERE ........
GROUP BY .......
Esta es la que necesito para ayudarte...
Hola, a continuación te cuelgo la SQL:
SELECT [nombreempleado] & " " & [apellido1] & " " & [apellido2] AS empleado, Sum(((Hour([extras]))-(Hour([descuentos])))+Int(((Minute([extras]))-(Minute([descuentos])))/60)) AS totalhorasextras, Sum(((((Minute([extras]))-(Minute([descuentos])))/60)-Int(((Minute([extras]))-(Minute([descuentos])))/60))*60) AS totalminutosextras, detalle.[?/extra], ([totalhorasextras]*[?/extra])+([totalminutosextras]*[?/extra]/60) AS pagoextras, Sum(Hour([jornada])) AS totalhorasjornada, [totalhorasjornada]/8 AS diastrabajo, detalle.[?/jornada], [diastrabajo]*[?/jornada] AS pagojornada, Sum(detalle.[a/c]) AS [SumaDea/c], Sum(detalle.atrasos) AS SumaDeatrasos, [pagoextras]+[pagojornada]-Sum([a/c])+Sum([atrasos]) AS [A pagar], partes.observaciones, detalle.alta, empleados.nomina, partes.ennomina
FROM (empleados INNER JOIN partes ON empleados.idempleado = partes.idempleado) INNER JOIN detalle ON partes.idparte = detalle.idparte
WHERE (((Month([fecha])) Like "*" & [NUMERO DEL MES]) AND ((Year([fecha])) Like "*" & [AÑO]))
GROUP BY [nombreempleado] & " " & [apellido1] & " " & [apellido2], detalle.[?/extra], detalle.[?/jornada], partes.observaciones, detalle.alta, empleados.nomina, partes.ennomina;
Gracias
Ahora entendí tu problema...
Mira, no hay solución en una sola consulta SQL, dado que el Operador PIVOT requiere tener previamente identificados los ids de las filas que quieres pasar a columnas. PIVOT se utiliza por ejemplo, para pasar los días de la semana de filas a columnas. En tu caso no sirve porque tendrías que colocar todos los ID de empleados en la consulta y creo que no es factible ni lo correcto.
Te puedo recomendar 2 soluciones, una es la salida funcional y la otra es de programación.
La funcional:
- Quita la columna observaciones y agrega el idempleado a la consulta, pero no lo muestres en el formulario (ponlo en algún tag de cada fila). Con esto se resuelve el problema de la agrupación. Pero, tienes que ofrecerle la posibilidad al usuario que revise las observaciones por cada idempleado. Entonces, puedes darle la posibilidad de seleccionar una fila y apretar un botón "Observaciones" y haces otra consulta que traiga sólo las observaciones (a esta consulta le pasas el idempleado de la fila seleccionada). Esto se lo puedes mostrar en un textbox, label o msgbox... a tu gusto...
La de programación:
- El proceso toma parte de la solución anterior y consiste principalmente en hacer la concatenación de las observaciones, pero en el mismo access (simulando una función SQL Server). Entonces, antes de mostrar los datos, tienes que hacer el proceso de traer todas las observaciones y concatenarlas. Estas observaciones concatenadas, las tienes que almacenar en una matriz, con su correspondiente idempleado en cada fila de la matriz. La consulta para esto es la misma de la solución funcional (SELECT idempleado, observaciones FROM partes ... ORDER BY idempleado). Vas recorriendo los registros y si el idempleado es igual al del registro anterior, concatenas (esto es un ciclo sencillo). Bueno, después de tener todas las observaciones concatenadas por cada idempleado, haces la consulta que ya tienes (sin observaciones) y vas recorriendo uno a uno y buscando en tu matriz de concatenados y se las vas poniendo al listado.
Mira, de las dos soluciones, me gusta más la funcional, porque es más sencilla, consume menos recursos y hasta creo que sería bueno para el usuario, porque no creo que quiera ver todas las observaciones, sino aquellas que le causen interés.
Sorry por no haber podido solucionar tu problema tal cual querías, pero no le encontré otra solución.
Suerte.
Respuesta
Al ser tu campo tipo memo es normal que no te lo deje concatenar tan fácilmente, para que lo concatenara tendrías que generar una consulta adicional, en la que realizara esa función, hacia una tabla te paso, a otro campo memo,
no lo aconsejo mucho más trabajo.
Si es necesario que lo muestres en el informe pon en ves de agrupar en la consulta que muestre primero, o un criterio en el que lo que aparezca de ese campo te sirva como información, o si lo quieres todo lo saques del detalle y lo pongas en el pie, pero de una referencia, ojo no es igual el pie del informe completo a de una agrupación.
Al estar fuera del detalle debería asociarlo sin problemas

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas