Processamento de conjuntos de dados em visões CDS

Objectives

After completing this lesson, you will be able to:
  • Descrever as técnicas de processamento de conjuntos de dados no ABAP CDS.
  • Utilize o suplemento DISTINCT em visões CDS ABAP.
  • Incluir agregações e agrupamento em visões CDS.
  • Use junções e uniões em visões CDS.

Síntese

O ABAP SQL oferece várias técnicas SQL para manipular e combinar conjuntos de dados. Eles também são suportados no CDS do ABAP? E se forem, quais são as diferenças?

Aqui está uma lista das técnicas SQL mais importantes:

ORDEM POR

A cláusula ORDER BY para classificar conjuntos de resultados não é suportada no CDS do ABAP.

DISTINTO

O suplemento DISTINCT é utilizado para remover entradas duplicadas do conjunto de resultados. Ele é suportado no ABAP CDS, mas com DISTINCT após a palavra-chave SELECT e não no início da lista de campos.

Agregações e GROUP BY

As agregações são utilizadas para derivar valores de todo um conjunto de dados, por exemplo, o número de registros, um valor máximo ou um valor médio. As agregações são frequentemente combinadas com uma cláusula GROUP BY que define grupos de registros antes de a agregação ser executada para cada grupo separadamente. Nem todas as agregações disponíveis no ABAP SQL também são suportadas em visões CDS, mas as agregações mais importantes, como COUNT, MIN, MAX, SUM e AVG, estão disponíveis. Há também pequenas diferenças na sintaxe. Por exemplo, é obrigatório indicar o tipo de resultado ao calcular uma média com AVG. No ABAP SQL, isso é apenas uma opção.

PARTICIPAR

As junções são utilizadas para combinar registros de diferentes conjuntos de resultados que correspondem a uma condição join. Os mesmos tipos de junção são suportados pelo ABAP SQL e pelo ABAP CDS. Novamente, existem algumas pequenas diferenças de sintaxe. É obrigatório indicar a fonte de dados ao acessar campos e o CDS ABAP utiliza um seletor de campos diferente.

UNION

A instrução UNION é utilizada para unir os registros de diferentes conjuntos de resultados. Ao utilizar UNION na definição de visões CDS, são aplicadas regras especiais para a definição de chave e os tipos, nomes e anotações de elementos de visão.

Vejamos um exemplo para cada uma dessas técnicas.

Resultados distintos no CDS do ABAP

A adição DISTINCT permite que você remova duplicados do conjunto de resultados de uma instrução SELECT. No ABAP SQL, ele é colocado no início da lista de campos. Nas definições de visão CDS, DISTINCT vem sempre diretamente após a instrução SELECT. Não faz parte da lista de elementos entre chaves.

Agregações em ABAP CDS

O exemplo mostra as funções agregadas mais comuns e como elas são usadas nas definições de visão CDS e ABAP SQL. Observe que a adição como abap.fltp dentro dos parênteses da função de agregação AVG( ) especifica o tipo numérico para o resultado. A adição do AS é obrigatória no CDS do ABAP. No ABAP SQL, é opcional e o tipo FLTP é usado por padrão.

Se a lista de elementos de uma instrução SELECT contiver uma mistura de funções agregadas e outros elementos, como colunas, expressões, etc., a sintaxe do SQL requer uma cláusula GROUP BY. A cláusula GROUP BY deve listar todos os campos da fonte de dados que aparecem na lista de campos fora das agregações.

O exemplo mostra que não há diferença na forma como você define a cláusula GROUP BY no ABAP SQL e no ABAP CDS.

Dica

O editor para definições de dados CDS oferece uma correção rápida para gerar a cláusula GROUP BY. Isso pode ser particularmente útil quando a lista de elementos é longa ou contém expressões complicadas. Outra correção rápida é oferecida depois de você ter efetuado modificações na lista de elementos, permitindo que você ajuste a cláusula GROUP BY-.

Testar: agregações em definições de visão CDS

  1. Criar uma nova definição de dados CDS sem um objeto de dados referenciado.
  2. Remova toda a instrução SELECT, incluindo a lista de elementos e as chaves circundantes.
  3. Copie o seguinte snippet de código e insira-o após 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. Ative a definição de dados, abra a ferramenta Visualização de dados e analise a saída.
  5. Remova os marcadores de comentário das agregações na lista de elementos. Observe que o ícone de erro para o erro de sintaxe A cláusula GROUP BY está ausente inclui uma lâmpada.
  6. Selecione o ícone de erro para chamar a correção rápida Adicionar cláusula GROUP BY. Considere que a cláusula GROUP BY gerada contém os campos DepartureAirport e DestinationAirport porque esses campos são utilizados para calcular a descrição do elemento de visão.
  7. Considere o erro de sintaxe A função AVG só é permitida com o suplemento "as" para o último elemento na lista de elementos.
  8. Remova o último elemento da lista de elementos e substitua-o pelo seguinte código:
    Code Snippet
    12
    avg( _Flight.OccupiedSeats as abap.dec(15,2)) as AverageOccupation
  9. Ative a definição de dados, abra a ferramenta Visualização de dados e analise a saída.

Junções e uniões no CDS do ABAP

Em SQL, uma junção é a combinação de duas fontes de dados em um conjunto de resultados, que consiste em colunas de ambas as fontes de dados. As linhas são determinadas pelo tipo join e pela condição join, também chamada de condição ON.

O ABAP CDS e o ABAP SQL suportam os mesmos tipos de junção, entre eles INNER JOIN, LEFT OUTER JOIN e RIGHT OUTER join. Para outros tipos de junção suportados, consulte a documentação de palavras-chave ABAP.

A sintaxe para joins é muito semelhante no ABAP SQL e no ABAP CDS, embora não seja idêntica. Vejamos um exemplo.

No CDS ABAP, o sinal de ponto (.) é utilizado como separador entre um nome de campo e o nome da fonte de dados ou, se um alias estiver definido para essa fonte de dados, o nome do alias da fonte de dados. Neste ABAP SQL, segue o padrão SQL. No ABAP SQL, o sinal til (~) é usado para esse fim. O motivo é que, em ABAP, o sinal do período já é utilizado como delimitador de instrução.

A outra diferença de sintaxe diz respeito à utilização de campos na lista de campos ou na lista de elementos. Nas entidades de visão CDS, o nome da fonte de dados é obrigatório para todos os campos. No ABAP SQL, o nome da fonte só é necessário quando existem campos com o mesmo nome em fontes de dados diferentes. No exemplo, este é o caso para o campo carrier_id porque existe um campo com esse nome em ambas as fontes de dados.

Um UNION consolida as linhas dos conjuntos de resultados de várias instruções SELECT de entidades de visão CDS em um conjunto de resultados. Sem o suplemento ADD, TODOS os duplicados completos são removidos após a consolidação.

Como pré-requisito para UNION ou UNION ALL, os conjuntos de resultados devem ter o mesmo número de elementos e os pares de elementos que ocorrem na mesma posição do conjunto de resultados devem ter um tipo de dados compatível. Este pré-requisito é idêntico no ABAP SQL e no CDS do ABAP.

Além disso, as seguintes regras se aplicam ao usar UNION ou UNION ALL em definições de visão CDS:

Nomes de elemento

Os nomes de elemento direto ou os nomes de alias devem corresponder para cada coluna nas listas de elementos.

Elementos-chave

Os elementos-chave de todas as listas de elementos devem corresponder. Caso contrário, ocorre um erro de verificação de sintaxe.

Anotações de elemento

Somente a lista de elementos da primeira instrução SELECT pode definir anotações de elemento. Em todas as ramificações subsequentes, as anotações de elemento são proibidas.

Para evitar conflitos, a anotação @Metadata.ignorePropagatedAnnotations: true é obrigatória quando uma definição de visão CDS contém UNION ou UNION ALL.

Experimente: junções e uniões nas definições de visão CDS

  1. Criar uma nova definição de dados CDS sem um objeto de dados referenciado.
  2. Remova toda a instrução SELECT, incluindo a lista de elementos e as chaves circundantes.
  3. Copie o seguinte snippet de código e insira-o após 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. Analise a definição da visão. Ele contém uma UNION ALL de duas SELECTS. O primeiro retorna os clientes, cada um com o número de viagens que reservaram. O segundo SELECT retorna agências de viagens, cada uma com o número de viagens que foram reservadas nessa agência de viagens. Você ainda não pode ativar a definição de dados devido a erros de sintaxe.
  5. Observe que o erro de sintaxe Número de campos em listas de seleção em uniões deve ser o mesmo e resolva-o removendo os marcadores de comentário do tipo de elemento no segundo SELECT.
  6. Observe que o erro de sintaxe Anotações não são permitidas nesta ramificação no segundo SELECT e resolva-a removendo o @endUserText.label. do segundo SELECT.
  7. Observe que o erro de sintaxe Definição de chave da ramificação 2 deve corresponder à definição de chave da ramificação 1 e resolva-a adicionando a chave à frente do tipo de elemento no segundo SELECT.

    Dica

    Atualmente, esta mensagem de erro só é exibida na visão Problemas e não na visão de editor.
  8. Quando todos os erros de sintaxe tiverem ocorrido, ative a definição de dados, abra a ferramenta Visualização de dados e analise a saída.

Processar conjuntos de dados em visões CDS

Você quer analisar mais detalhadamente os dados do empregado e do departamento. Para isso, você utiliza o suplemento DISTINCT, agregações, agrupamento e junções em uma entidade de visão CDS.

Modelo:

  • n.a.

Solução:

  • /LRN/C_DEPARTMENT_QRY (Definição de dados)

Tarefa 1: Utilizar DISTINCT

Defina uma nova entidade de visão CDS (nome sugerido: Z##_C_DepartmentQuery) que retorna o ID e a descrição dos departamentos que têm pelo menos um empregado atribuído a ela. Como fonte de dados, utilize sua entidade de visão para dados do empregado com funções, mas sem parâmetros (o nome sugerido era: Z##_C_EmployeeQuery). Certifique-se de que cada departamento esteja listado apenas uma vez.

Nota

Se você não tiver concluído o exercício anterior, pode permitir que sua nova entidade de visão leia a partir da entidade de visão /LRN/C_Employee_Fnc.

Etapas

  1. Em seu próprio pacote, crie uma nova definição de dados (nome sugerido: Z##_C_DEPARTMENTQUERY, em que ## é o número do seu grupo). Indique sua entidade de visão CDS Z##_C_EmployeeQuery como Objeto referenciado e selecione o modelo Definir entidade de visão para gerar a declaração de definição, algumas anotações padrão e a lista de elementos.

    1. Na visão Explorador de projetos, clique com o botão direito do mouse em sua definição de dados Z##_C_EMPLOYEEQUERY para abrir o menu de contexto.

    2. No menu de contexto, selecione Nova definição de dados.

    3. Confirme que o campo Pacote contém o nome do seu pacote e que o campo Objeto referenciado contém o nome da sua definição de tabela de banco de dados.

    4. No campo Nome, insira o nome para a entidade da visão CDS (Z##_C_DepartmentQuery, em que ## é o seu número de grupo).

    5. Insira Departamento (consulta) no campo Descrição e selecione Seguinte.

    6. Confirme a ordem de transporte e selecione Seguinte.

      Cuidado

      Certifique-se de que você ainda não selecionou Concluir. Se fizer isso, você não poderá escolher o modelo que deseja usar.
    7. A partir da lista de modelos, selecione Definir entidade de visão e, em seguida, selecione Concluir.

  2. Aplique a formatação do código-fonte.

    1. No menu eclipse, selecione Formato→do texto fonte. Como alternativa, selecione Shift + F1.

  3. Edite a lista de elementos da nova definição de dados. Remova todos os elementos, exceto DepartmentID e DepartmentDescription.

    1. Ajuste o código da seguinte forma:

      Code Snippet
      12345678
      define view entity Z##_C_DepartmentQuery as select from Z##_C_EmployeeQuery { DepartmentId, DepartmentDescription }
  4. Ative a definição de dados e exiba o resultado da consulta na ferramenta Visualização de dados.

    1. Pressione Ctrl + F3 para ativar o objeto de desenvolvimento.

    2. Pressione F8 para chamar a ferramenta Visualização de dados.

  5. Edite a definição de dados e adicione o suplemento DISTINCT à instrução SELECT.

    1. Ajuste o código da seguinte forma:

      Code Snippet
      12345678
      define view entity Z##_C_DepartmentQuery as select distinct from Z##_C_EmployeeQuery { DepartmentId, DepartmentDescription }
  6. Ative a definição de dados e exiba novamente o resultado da query.

    1. Pressione Ctrl + F3 para ativar o objeto de desenvolvimento.

    2. Pressione F8 para chamar a ferramenta Visualização de dados.

Tarefa 2: Utilizar agregações e agrupamento

Para cada departamento, calcule a média de afiliação da empresa e o salário anual total dos funcionários atribuídos a esse departamento.

Etapas

  1. Remova o suplemento DISTINCT da sua definição de dados.

    1. Ajuste o código da seguinte forma:

      Code Snippet
      12345678
      define view entity Z##_C_DepartmentQuery as select from Z##_C_EmployeeQuery { DepartmentId, DepartmentDescription }
  2. No final da lista de elementos, adicione um novo elemento de visualização (nome sugerido: AverageAffiliation). Utilize a função agregada AVG com o argumento CompanyAffiliation.

    1. Ajuste o código da seguinte forma:

      Code Snippet
      123456789
      define view entity Z##_C_DepartmentQuery as select from Z##_C_EmployeeQuery { DepartmentId, DepartmentDescription, avg( CompanyAffiliation ) as AverageAffiliation }
  3. Certifique-se de que o resultado tem o mesmo tipo que o elemento CompanyAffiliation da entidade de visão de origem.

    1. Posicione o cursor em CompanyAffiliation e pressione F2 para exibir as informações do elemento de código. O tipo de CompanyAffiliation é abap.dec(11,1).

    2. Ajuste o código da seguinte forma:

      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. Adicione um novo elemento de visualização (nome sugerido: TotalSalary). Use a função de agregação SUM com o argumento AnnualSalaryConverted.

    1. Ajuste o código da seguinte forma:

      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. Adicione o código de moeda à lista de elementos e anote o campo de montante com @Semantics.amount.currencyCode.

    1. Ajuste o código da seguinte forma:

      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. Use uma correção rápida para gerar a cláusula GROUP BY.

    1. Posicione o cursor em select e pressione Ctrl + 1 para chamar a correção rápida. Como alternativa, escolha o ícone de erro com uma lâmpada no lado esquerdo dessa linha de código.

    2. Na lista de soluções rápidas disponíveis, selecione Adicionar cláusula GROUP BY.

    3. Depois de aplicar a correção rápida, o código deve ter o seguinte 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. Ative a definição de dados e exiba novamente o resultado da query.

    1. Pressione Ctrl + F3 para ativar o objeto de desenvolvimento.

    2. Pressione F8 para chamar a ferramenta Visualização de dados.

Tarefa 3: Parâmetros de entrada de suprimento

Substitua a fonte de dados pela sua visão que fornece parâmetros de entrada (o nome sugerido foi: Z##_C_EmployeeQueryP). Para fornecer os parâmetros, adicione os mesmos parâmetros à sua nova visão e encaminhe-os para a visão da fonte.

Nota

Se você não tiver concluído o exercício anterior, leia a partir da entidade de visão CDS /LRN/C_Employee_Par.

Etapas

  1. Na cláusula FROM, substitua a fonte de dados e use sua entidade de visão com parâmetros. Use o code completion para inserir a assinatura completa da fonte de dados, ou seja, a entidade de visão CDS com os respectivos parâmetros.

    1. Na cláusula FROM, substitua Z##_C_EmployeeQuery por Z##_C_EmployeeQueryP. Se você usou /LRN/C_Employee_Fnc, substitua-o por /LRN/C_Employee_Par.

    2. Posicione o cursor imediatamente após o nome da entidade e pressione Ctrl + espaço para chamar a conclusão de código.

    3. Pressione Shift + Enter para inserir a entidade de visão com assinatura completa.

    4. A conclusão de código deve ajustar o código da seguinte forma:

      Code Snippet
      12345
      define view entity Z##_C_DepartmentQuery as select from Z##_C_EmployeeQueryP( p_target_curr: , p_date: )
  2. Defina dois parâmetros de entrada para sua visão. Use os mesmos nomes de parâmetro, tipos e anotações usados na fonte de dados.

    Dica

    É mais fácil copiar as definições de parâmetro da fonte de dados.
    1. Mantenha pressionada a tecla Strg e selecione o nome da visão após FROM para navegar para a fonte de dados.

    2. Selecione o código antes de as select, incluindo o suplemento WITH PARAMETERS e pressione Ctrl + C para copiar a definição do parâmetro para o clipboard.

    3. Retorne à sua definição de dados e insira a definição de parâmetro antes de as select.

    4. O código deve ter o seguinte 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. Use os novos parâmetros como entrada para a fonte de dados.

    1. Ajuste o código da seguinte forma:

      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. Na lista de elementos, ajuste o nome do elemento do código de moeda, ou seja, remova o sufixo USD.

    1. ajuste o código da seguinte forma:

      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. Ative e teste a definição de dados.

    1. Pressione Ctrl + F3 para ativar o objeto de desenvolvimento.

    2. Pressione F8 para chamar a ferramenta Visualização de dados.

    3. Utilize valores diferentes para o parâmetro P_TARGET_CURR.

Tarefa 4: Usar uma junção externa

Você quer ver todos os departamentos, mesmo aqueles que não têm empregados atribuídos a eles. Para isso, use uma junção externa da fonte de dados atual e sua entidade de visão para dados do departamento (o nome sugerido era: Z##_R_Department).

Nota

Se você não tiver concluído o exercício sobre associações, utilize a entidade de visão CDS /LRN/C_Department_Rel.

Etapas

  1. Em sua entidade de visão Z##_C_DepartmentQuery, ajuste a cláusula FROM. No final da cláusula, adicione uma junção externa direita da sua entidade de visão CDS para dados do departamento.

    1. Ajuste o código da seguinte forma:

      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 nomes de alias para as duas fontes de dados (nomes sugeridos: e para funcionário e d para departamento) e adicione a condição ON.

    1. Ajuste o código da seguinte forma:

      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. Na lista de elementos, leia o ID do departamento e a descrição do departamento da entidade de visão do departamento em vez da entidade de visão do empregado e transforme o ID do departamento em um elemento-chave.

    1. Ajuste o código da seguinte forma:

      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. Remova a cláusula GROUP BY e gere-a novamente usando a correção rápida.

    1. Ajuste o código da seguinte forma:

      Code Snippet
      123456
      group by d.Id, d.Description, CurrencyCode
  5. Adicione o alias da tabela como prefixo quando solicitado pela verificação de sintaxe.

    1. Ajuste o código da seguinte forma:

      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. Ative e teste a definição de dados.

    1. Pressione Ctrl + F3 para ativar o objeto de desenvolvimento.

    2. Pressione F8 para chamar a ferramenta Visualização de dados.