Procesamiento de conjuntos de datos en vistas CDS

Objectives

After completing this lesson, you will be able to:
  • Describa las técnicas para procesar conjuntos de datos en ABAP CDS.
  • Utilice el suplemento DISTINCT en las vistas CDS ABAP.
  • Incluir agregaciones y agrupaciones en vistas CDS.
  • Utilice joins y uniones en vistas CDS.

Resumen

ABAP SQL ofrece varias técnicas SQL para manipular y combinar conjuntos de datos. ¿También se admiten en ABAP CDS? Y si lo son, ¿cuáles son las diferencias?

Aquí hay una lista de las técnicas SQL más importantes:

ORDEN POR

La cláusula ORDER BY para clasificar conjuntos de resultados no se admite en ABAP CDS.

DISTINCT

El suplemento DISTINCT se utiliza para eliminar entradas duplicadas del conjunto de resultados. Se admite en ABAP CDS, pero con DISTINCT después de la palabra clave SELECT y no al principio de la lista de campos.

Agregaciones y GROUP BY

Las agregaciones se utilizan para derivar valores de todo un conjunto de datos, por ejemplo, el número de registros, un valor máximo o un valor medio. Las agregaciones a menudo se combinan con una cláusula GROUP BY que define grupos de registros antes de que la agregación se realice para cada grupo por separado. No todas las agregaciones que están disponibles en ABAP SQL también se admiten en las vistas CDS, pero las agregaciones más importantes, como COUNT, MIN, MAX, SUM y AVG, están disponibles. También hay pequeñas diferencias en la sintaxis. Por ejemplo, es obligatorio especificar el tipo de resultado al calcular un promedio con AVG. En ABAP SQL, esto es solo una opción.

CONEXIÓN

Las combinaciones se utilizan para combinar registros de diferentes conjuntos de resultados que coinciden con una condición de unión. ABAP SQL y ABAP CDS admiten los mismos tipos de conexión. De nuevo, hay algunas diferencias de sintaxis menores. Es obligatorio especificar la fuente de datos al acceder a los campos y ABAP CDS utiliza un selector de campos diferente.

UNIÓN

La sentencia UNION se utiliza para unir los registros de diferentes conjuntos de resultados. Al utilizar UNION en la definición de vistas CDS, se aplican reglas especiales para la definición de clave y los tipos, nombres y anotaciones de elementos de vista.

Veamos un ejemplo de cada una de estas técnicas.

Resultados distintos en ABAP CDS

El suplemento DISTINCT le permite eliminar duplicados del conjunto de resultados de una sentencia SELECT. En ABAP SQL, se coloca al principio de la lista de campos. En las definiciones de vista CDS, DISTINCT siempre viene directamente después de la sentencia SELECT. No forma parte de la lista de elementos entre corchetes.

Agregaciones en ABAP CDS

El ejemplo muestra las funciones agregadas más comunes y cómo se utilizan en ABAP SQL y definiciones de vistas CDS. Tenga en cuenta que la adición como abap.fltp dentro de los paréntesis de la función agregada AVG( ) especifica el tipo numérico para el resultado. El suplemento AS es obligatorio en ABAP CDS. En ABAP SQL es opcional y el tipo FLTP se utiliza por defecto.

Si la lista de elementos de una sentencia SELECT contiene una mezcla de funciones agregadas y otros elementos, como columnas, expresiones, etc., la sintaxis de SQL requiere una cláusula GROUP BY. La cláusula GROUP BY debe enumerar todos los campos de la fuente de datos que aparecen en la lista de campos fuera de las agregaciones.

El ejemplo muestra que no hay diferencia en la forma en que define la cláusula GROUP BY en ABAP SQL y ABAP CDS.

Consejo

El editor de definiciones de datos CDS ofrece una corrección rápida para generar la cláusula GROUP BY. Esto puede ser especialmente útil cuando la lista de elementos es larga o contiene expresiones complicadas. Se ofrece otra corrección rápida después de realizar modificaciones en la lista de elementos, lo que le permite ajustar la cláusula GROUP BY.

Pruébelo: Agregaciones en definiciones de vista CDS

  1. Cree una nueva definición de datos CDS sin un objeto de datos referenciado.
  2. Elimine toda la sentencia SELECT, incluida la lista de elementos y los corchetes circundantes.
  3. Copie el siguiente fragmento de código e insértelo después de as:
    Code Snippet
    123456789101112131415161718192021222324
    select from /DMO/I_Connection_R { key AirlineID, key ConnectionID, concat_with_space( concat_with_space( concat_with_space( concat( concat( AirlineID, ConnectionID ), ': ' ), DepartureAirport, 1 ), '->', 1 ), DestinationAirport, 1 ) as Description // , //count( distinct _Flight.FlightDate ) as NumberOfFlights, //min( _Flight.FlightDate ) as FirstFlightDate, //sum( _Flight.OccupiedSeats ) as TotalOccupiedSeats, //avg( _Flight.OccupiedSeats ) as AverageOccupation }
  4. Active la definición de datos, abra la herramienta Vista previa de datos y analice la salida.
  5. Elimine los marcadores de comentarios de las agregaciones en la lista de elementos. Tenga en cuenta que el icono de error para el error de sintaxis Falta la cláusula GROUP BY incluye una bombilla.
  6. Seleccione el icono de error para invocar la cláusula de solución rápida Añadir GROUP BY. Tenga en cuenta que la cláusula GROUP BY generada contiene los campos DepartureAirport y DestinationAirport porque estos campos se utilizan para calcular el elemento de vista Description.
  7. Tenga en cuenta que el error de sintaxis Función AVG solo se permite con el suplemento "as" para el último elemento de la lista de elementos.
  8. Elimine el último elemento de la lista de elementos y sustitúyalo por el siguiente código:
    Code Snippet
    12
    avg( _Flight.OccupiedSeats as abap.dec(15,2)) as AverageOccupation
  9. Active la definición de datos, abra la herramienta Vista previa de datos y analice la salida.

Uniones y uniones en ABAP CDS

En SQL, una combinación es la combinación de dos fuentes de datos en un conjunto de resultados, que consta de columnas de ambas fuentes de datos. Las filas se determinan mediante el tipo de conexión y la condición de conexión, también llamada condición ON.

ABAP CDS y ABAP SQL admiten los mismos tipos de join, entre ellos INNER JOIN, LEFT OUTER JOIN y RIGHT OUTER join. Para otros tipos de join admitidos, consulte la documentación de palabras clave ABAP.

La sintaxis de los joins es muy similar en ABAP SQL y ABAP CDS, aunque no es idéntica. Veamos un ejemplo.

En ABAP CDS, el signo de período (.) se utiliza como separador entre un nombre de campo y el nombre de la fuente de datos o, si se define un alias para esta fuente de datos, el nombre alias de la fuente de datos. En este SQL ABAP sigue el estándar SQL. En ABAP SQL, el signo de tilde (~) se utiliza para este fin. El motivo es que en ABAP, el signo de período ya se utiliza como delimitador de sentencia.

La otra diferencia de sintaxis se refiere a la utilización de campos en la lista de campos o en la lista de elementos. En las entidades de vista CDS, el nombre de la fuente de datos es obligatorio para todos los campos. En ABAP SQL, el nombre de fuente solo es necesario cuando hay campos del mismo nombre en diferentes fuentes de datos. En el ejemplo, este es el caso del campo carrier_id porque existe un campo con ese nombre en ambas fuentes de datos.

Una UNION fusiona las filas de los conjuntos de resultados de varias sentencias SELECT de entidades de vista CDS en un conjunto de resultados. Sin el suplemento ADD, ALL, los duplicados completos se eliminan después de la fusión.

Como requisito previo para UNION o UNION ALL, los conjuntos de resultados deben tener el mismo número de elementos y los pares de elementos que aparecen en la misma posición del conjunto de resultados deben tener un tipo de datos compatible. Este requisito previo es idéntico en ABAP SQL y en ABAP CDS.

Además, se aplican las siguientes reglas al utilizar UNION o UNION ALL en definiciones de vista CDS:

Nombres de elemento

Los nombres de elementos directos o los nombres de alias deben coincidir para cada columna de las listas de elementos.

Elementos clave

Los elementos clave de todas las listas de elementos deben coincidir. De lo contrario, se produce un error de verificación de sintaxis.

Anotaciones de elemento

Solo la lista de elementos de la primera sentencia SELECT puede definir anotaciones de elemento. En todas las ramificaciones posteriores, las anotaciones de elemento están prohibidas.

Para evitar conflictos, la anotación @Metadata.ignorePropagatedAnnotations: true es obligatoria cuando una definición de vista CDS contiene UNION o UNION ALL.

Pruébelo: uniones y uniones en definiciones de vista CDS

  1. Cree una nueva definición de datos CDS sin un objeto de datos referenciado.
  2. Elimine toda la sentencia SELECT, incluida la lista de elementos y los corchetes circundantes.
  3. Copie el siguiente fragmento de código e insértelo después de as:
    Code Snippet
    12345678910111213141516171819202122232425262728293031323334
    select from /dmo/customer as c inner join /dmo/travel as t on c.customer_id = t.customer_id { key c.customer_id as id, key 'C' as type, concat_with_space( c.last_name, c.first_name, 1 ) as name, @EndUserText.label: 'Number of Bookings' count( distinct t.travel_id ) as TravelsCount } group by c.customer_id, c.last_name, c.first_name union all select from /dmo/agency as a inner join /dmo/travel as t on a.agency_id = t.agency_id { key a.agency_id, // key 'A' as type, a.name, @EndUserText.label: 'Number of Bookings' count( distinct t.travel_id) as TravelsCount } group by a.agency_id, a.name
  4. Analice la definición de vista. Contiene una UNION ALL de dos SELECTS. El primero devuelve clientes, cada uno con el número de viajes que reservaron. La segunda SELECT devuelve las agencias de viajes, cada una con el número de viajes que se reservaron en esa agencia de viajes. Aún no puede activar la definición de datos debido a errores de sintaxis.
  5. Tenga en cuenta el error de sintaxis El número de campos en las listas de selección en las uniones debe ser el mismo y resuélvalo eliminando los marcadores de comentarios del tipo de elemento en la segunda SELECT.
  6. Observe el error de sintaxis No se permiten anotaciones en esta rama en la segunda SELECT y resuélvala eliminando @endUserText.label. de la segunda SELECT.
  7. Tenga en cuenta el error de sintaxis La definición de clave de ramificación 2 debe coincidir con la definición de clave de ramificación 1 y resolverla añadiendo la clave delante del tipo de elemento en la segunda SELECT.

    Consejo

    Actualmente, este mensaje de error solo se visualiza en la vista Problemas, no en la vista del editor.
  8. Cuando hayan desaparecido todos los errores de sintaxis, active la definición de datos, abra la herramienta Vista previa de datos y analice la salida.

Procesar conjuntos de datos en vistas CDS

Desea seguir analizando los datos de empleado y departamento. Para ello, utilice el suplemento DISTINCT, agregaciones, agrupaciones y joins en una entidad de vista CDS.

Modelo:

  • n.a.

Solución:

  • /LRN/C_DEPARTMENT_QRY (Definición de datos)

Tarea 1: Utilizar DISTINCT

Defina una nueva entidad de vista CDS (nombre sugerido: Z##_C_DepartmentQuery) que devuelva el ID y la descripción de los departamentos que tienen al menos un empleado asignado. Como fuente de datos, utilice su entidad de vista para datos de empleado con funciones pero sin parámetros (el nombre sugerido era: Z##_C_EmployeeQuery). Asegúrese de que cada departamento aparezca solo una vez.

Nota

Si no ha finalizado el ejercicio anterior, puede dejar que su nueva entidad de vista lea la entidad de vista /LRN/C_Employee_Fnc.

Pasos

  1. En su propio paquete, cree una nueva definición de datos (nombre sugerido: Z##_C_DEPARTMENTQUERY, donde ## es su número de grupo). Especifique la entidad de vista CDS Z##_C_EmployeeQuery como objeto referenciado y seleccione el modelo Definir entidad de vista para generar la sentencia de definición, algunas anotaciones estándar y la lista de elementos.

    1. En la vista Explorador de proyectos, haga clic con el botón derecho en la definición de datos Z##_C_EMPLOYEEQUERY para abrir el menú contextual.

    2. En el menú contextual, seleccione Nueva definición de datos.

    3. Confirme que el campo Paquete contiene el nombre de su paquete y que el campo Objeto referenciado contiene el nombre de su definición de tabla de base de datos.

    4. En el campo Nombre, introduzca el nombre de la entidad de vista CDS (Z##_C_DepartmentQuery, donde ## es su número de grupo).

    5. Introduzca Departamento (consulta) en el campo Descripción y seleccione Siguiente.

    6. Confirme la orden de transporte y seleccione Siguiente.

      Atención

      Asegúrese de que aún no selecciona Finalizar. Si lo hace, no podrá seleccionar la plantilla que desea utilizar.
    7. En la lista de plantillas, seleccione Definir entidad de vista y, a continuación, Finalizar.

  2. Aplicar formato de código fuente.

    1. En el menú Eclipse, seleccione Formato→de código fuente. Como alternativa, seleccione Mayús + F1.

  3. Edite la lista de elementos de la nueva definición de datos. Elimine todos los elementos excepto DepartmentID y DepartmentDescription.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      12345678
      define view entity Z##_C_DepartmentQuery as select from Z##_C_EmployeeQuery { DepartmentId, DepartmentDescription }
  4. Active la definición de datos y visualice el resultado de la consulta en la herramienta Vista previa de datos.

    1. Pulse Ctrl + F3 para activar el objeto de desarrollo.

    2. Presione F8 para invocar la herramienta Vista previa de datos.

  5. Edite la definición de datos y añada el suplemento DISTINCT a la sentencia SELECT.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      12345678
      define view entity Z##_C_DepartmentQuery as select distinct from Z##_C_EmployeeQuery { DepartmentId, DepartmentDescription }
  6. Active la definición de datos y visualice de nuevo el resultado de la consulta.

    1. Pulse Ctrl + F3 para activar el objeto de desarrollo.

    2. Presione F8 para invocar la herramienta Vista previa de datos.

Tarea 2: Utilizar agregaciones y agrupaciones

Para cada departamento, calcule el promedio de afiliación a la empresa y el salario anual total de los empleados asignados a este departamento.

Pasos

  1. Elimine el suplemento DISTINCT de su definición de datos.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      12345678
      define view entity Z##_C_DepartmentQuery as select from Z##_C_EmployeeQuery { DepartmentId, DepartmentDescription }
  2. Al final de la lista de elementos, añada un nuevo elemento de vista (nombre sugerido: AverageAffiliation). Utilice la función de agregación AVG con el argumento CompanyAffiliation.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      123456789
      define view entity Z##_C_DepartmentQuery as select from Z##_C_EmployeeQuery { DepartmentId, DepartmentDescription, avg( CompanyAffiliation ) as AverageAffiliation }
  3. Asegúrese de que el resultado tenga el mismo tipo que el elemento CompanyAffiliation de la entidad de la vista fuente.

    1. Sitúe el cursor en CompanyAffiliation y pulse F2 para visualizar la información del elemento de código. El tipo de CompanyAffiliation es abap.dec(11,1).

    2. Ajuste el código de la siguiente manera:

      Code Snippet
      123456789
      define view entity Z##_C_DepartmentQuery as select from Z##_C_EmployeeQuery { DepartmentId, DepartmentDescription, avg( CompanyAffiliation as abap.dec(11,1) ) as AverageAffiliation }
  4. Añada un nuevo elemento de vista (nombre sugerido: TotalSalary). Utilice la función de agregación SUM con el argumento AnnualSalaryConverted.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      1234567891011
      define view entity Z##_C_DepartmentQuery as select from Z##_C_EmployeeQuery { DepartmentId, DepartmentDescription, avg( CompanyAffiliation as abap.dec(11,1) ) as AverageAffiliation, sum( AnnualSalaryConverted ) as TotalSalary }
  5. Añada el código de moneda a la lista de elementos y anote el campo de importe con @Semantics.amount.currencyCode.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      123456789101112
      define view entity Z##_C_DepartmentQuery as select from Z##_C_EmployeeQuery { DepartmentId, DepartmentDescription, avg( CompanyAffiliation as abap.dec(11,1) ) as AverageAffiliation, @Semantics.amount.currencyCode: 'CurrencyCodeUSD' sum( AnnualSalaryConverted ) as TotalSalary, CurrencyCodeUSD }
  6. Utilice una corrección rápida para generar la cláusula GROUP BY.

    1. Sitúe el cursor en select y pulse Ctrl + 1 para invocar la corrección rápida. Como alternativa, seleccione el icono de error con una bombilla en la parte izquierda de esa fila de código.

    2. En la lista de correcciones rápidas disponibles, seleccione la cláusula Añadir GROUP BY.

    3. Después de aplicar la corrección rápida, el código debería tener el siguiente aspecto:

      Code Snippet
      12345678910111213141516
      define view entity Z##_C_DepartmentQuery as select from Z##_C_EmployeeQuery { DepartmentId, DepartmentDescription, avg( CompanyAffiliation as abap.dec(11,1) ) as AverageAffiliation, @Semantics.amount.currencyCode: 'CurrencyCodeUSD' sum( AnnualSalaryConverted ) as TotalSalary, CurrencyCodeUSD } group by DepartmentId, DepartmentDescription, CurrencyCodeUSD
  7. Active la definición de datos y visualice de nuevo el resultado de la consulta.

    1. Pulse Ctrl + F3 para activar el objeto de desarrollo.

    2. Presione F8 para invocar la herramienta Vista previa de datos.

Tarea 3: Parámetros de entrada de aprovisionamiento

Sustituya la fuente de datos por su vista que proporciona parámetros de entrada (el nombre sugerido era: Z##_C_EmployeeQueryP). Para proporcionar los parámetros, añada los mismos parámetros a la nueva vista y reenvíelos a la vista de origen.

Nota

Si no ha finalizado el ejercicio anterior, lea en su lugar la entidad de la vista CDS /LRN/C_Employee_Par.

Pasos

  1. En la cláusula FROM, sustituya la fuente de datos y utilice su entidad view con parámetros. Utilice la compleción de código para insertar la firma completa de la fuente de datos, es decir, la entidad de vista CDS con sus parámetros.

    1. En la cláusula FROM, sustituya Z##_C_EmployeeQuery por Z##_C_EmployeeQueryP. Si ha utilizado /LRN/C_Employee_Fnc, sustitúyalo por /LRN/C_Employee_Par.

    2. Coloque el cursor inmediatamente después del nombre de la entidad y pulse Ctrl + Espacio para invocar la finalización del código.

    3. Pulse Mayús + Intro para insertar la entidad de vista con firma completa.

    4. La compleción de código debe ajustar el código de la siguiente manera:

      Code Snippet
      12345
      define view entity Z##_C_DepartmentQuery as select from Z##_C_EmployeeQueryP( p_target_curr: , p_date: )
  2. Defina dos parámetros de entrada para su vista. Utilice los mismos nombres de parámetro, tipos y anotaciones que se utilizan en la fuente de datos.

    Consejo

    Es más fácil si copia las definiciones de parámetro de la fuente de datos.
    1. Mantenga pulsada la tecla Strg y seleccione el nombre de la vista después de FROM para navegar a la fuente de datos.

    2. Seleccione el código antes de as select, incluido el suplemento WITH PARAMETERS y pulse Ctrl + C para copiar la definición de parámetro en el portapapeles.

    3. Vuelva a su definición de datos e inserte la definición de parámetro antes de as select.

    4. El código ahora debería tener el siguiente aspecto:

      Code Snippet
      12345678910
      define view entity Z##_C_DepartmentQuery with parameters p_target_curr : /dmo/currency_code, @EndUserText.label: 'Date of evaluation' @Environment.systemField: #SYSTEM_DATE p_date : abap.dats as select from Z##_C_EmployeeQueryP( p_target_curr: , p_date: )
  3. Utilice los nuevos parámetros como entrada para la fuente de datos.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      123456789101112
      define view entity Z##_C_DepartmentQuery with parameters p_target_curr : /dmo/currency_code, @EndUserText.label: 'Date of evaluation' @Environment.systemField: #SYSTEM_DATE p_date : abap.dats as select from Z##_C_EmployeeQueryP( p_target_curr: $parameters.p_target_curr, p_date: $parameters.p_date )
  4. En la lista de elementos, ajuste el nombre del elemento de código de moneda, es decir, elimine el sufijo USD.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      12345678910111213141516
      { DepartmentId, DepartmentDescription, avg( CompanyAffiliation as abap.dec(11,1) ) as AverageAffiliation, @Semantics.amount.currencyCode: 'CurrencyCode' sum( AnnualSalaryConverted ) as TotalSalary, CurrencyCode } group by DepartmentId, DepartmentDescription, CurrencyCode
  5. Active y pruebe la definición de datos.

    1. Pulse Ctrl + F3 para activar el objeto de desarrollo.

    2. Presione F8 para invocar la herramienta Vista previa de datos.

    3. Utilice valores diferentes para el parámetro P_TARGET_CURR.

Tarea 4: Utilizar una combinación externa

Desea ver todos los departamentos, incluso aquellos que no tienen empleados asignados. Para lograrlo, utilice una unión externa de la fuente de datos actual y su entidad de vista para datos de departamento (el nombre sugerido era: Z##_R_Department).

Nota

Si no ha finalizado el ejercicio sobre asociaciones, utilice la entidad de vista CDS /LRN/C_Department_Rel en su lugar.

Pasos

  1. En la entidad de vista Z##_C_DepartmentQuery, ajuste la cláusula FROM. Al final de la cláusula, añada una unión externa derecha de su entidad de vista CDS para datos de departamento.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      1234567
      as select from Z##_C_EmployeeQueryP( p_target_curr: $parameters.p_target_curr, p_date: $parameters.p_date ) right outer join Z##_R_Department
  2. Defina nombres alias para las dos fuentes de datos (nombres sugeridos: e para empleado y d para departamento) y añada la condición ON.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      12345678
      as select from Z##_C_EmployeeQueryP( p_target_curr: $parameters.p_target_curr, p_date: $parameters.p_date ) as e right outer join Z##_R_Department as d on e.DepartmentId = d.Id
  3. En la lista de elementos, lea el ID de departamento y la descripción de departamento de la entidad de vista de departamento en lugar de la entidad de vista de empleado y convierta el ID de departamento en un elemento clave.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      12345678910
      { d.Id, d.Description, avg( CompanyAffiliation as abap.dec(11,1) ) as AverageAffiliation, @Semantics.amount.currencyCode: 'CurrencyCode' sum( AnnualSalaryConverted ) as TotalSalary, CurrencyCode }
  4. Elimine la cláusula GROUP BY y vuelva a generarla con la corrección rápida.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      123456
      group by d.Id, d.Description, CurrencyCode
  5. Añada el alias de tabla como prefijo cuando lo solicite la verificación de sintaxis.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      1234567891011121314
      { d.Id, d.Description, avg( e.CompanyAffiliation as abap.dec(11,1) ) as AverageAffiliation, @Semantics.amount.currencyCode: 'CurrencyCode' sum( e.AnnualSalaryConverted ) as TotalSalary, e.CurrencyCode } group by d.Id, d.Description, e.CurrencyCode
  6. Active y pruebe la definición de datos.

    1. Pulse Ctrl + F3 para activar el objeto de desarrollo.

    2. Presione F8 para invocar la herramienta Vista previa de datos.