CDS Views
CDS Views
CDS Views
SELECT carrid,
connid,
fltime + 120 AS total_time
DIVISION( fltime, 60, 2 ) AS fltime
FROM spfli
WHERE carrid IN @s_carrid
INTO TABLE @DATA(result).
SELECT SINGLE
CONCAT( char1, char2 ) AS concat,
LENGTH( char1 ) AS length,
LEFT( char1, 3 ) AS left,
LOWER( char2 ) AS lower,
UPPER( char2 ) AS upper,
RIGHT( char1, 3 ) AS right,
SUBSTRING( char1, 3, 3 ) AS substring,
REPLACE( char1, ',' , '.' ) AS replace,
CONCAT_WITH_SPACE( char1, char2, 1 ) AS concat_with_space
FROM demo_expressions
INTO @DATA(result).
** Aggregate query
SELECT carrid,
SUM( price ) AS total_price,
FROM sflight
GROUP BY carrid
INTO TABLE @DATA(result).
to use the expressions we use as part of the field list in the GROUP BY… HAVING
clause.
DATA(lv_city_from) = 'BERLIN'.
Inner Join
Join the table with the ON condition. Inner join means, the data is selected only
if data is found in both tables.
Here, scarr is the left-table and SPFLI is the right-table. The data is selected
from the left-table and if a matching record is found in the right-table, fields
from the right-table are populated, else they have an initial value.
DATA(lv_city_from) = 'BERLIN'.
Coalesce
For outer joins, if you need to add a specific value for the field where the entry
in the outer table does not exist – Coalesce can be used.
DATA(lv_city_from) = 'BERLIN'.
Here as well, scarr is the left-table and SPFLI is the right-table. The data is
selected from the right table and if a matching record is found in the left-table,
fields from the left-table are populated, else they have an initial value.
DATA(lv_city_from) = 'BERLIN'.
SELECT
FROM sflight INNER JOIN spfli
ON sflight~carrid = spfli~carrid AND
sflight~connid = spfli~connid
FIELDS spfli~*, sflight~fldate
INTO TABLE @DATA(result).
"Before 7.50
SELECT schedule~carrid, schedule~connid, schedule~fldate,
flight~cityfrom, flight~cityto
FROM sflight AS schedule INNER JOIN spfli AS flight
ON schedule~carrid = flight~carrid AND
schedule~connid = flight~connid
WHERE flight~cityfrom = 'FRANKFURT'
INTO TABLE @DATA(lt_flights).
"From 7.50
Notice that the INTO clause moves to the end. So it would be a good habit if we
move the clause to the end for all the queries. Also, if we want only the unique
records, we can use UNION DISTINCT instead of UNION ALL. ( If nothing is specified
after UNION, the default mode used is DISTINCT ).
Important:
The Union can also work on selecting data from different tables as long as the same
fields are selected.
UNION queries can not use FOR ALL ENTRIES
AGGREGATEs can be used in UNION queries
we can not use select * and by default union distinct union all will give
duplicates also
UNION ALL
SELECT schedule~carrid, schedule~connid, schedule~fldate,
flight~cityfrom, flight~cityto
FROM sflight AS schedule INNER JOIN spfli AS flight
ON schedule~carrid = flight~carrid AND
schedule~connid = flight~connid
WHERE flight~cityfrom = 'SAN FRANCISCO'
When we write aggregate queries, we get aggregate values based on the fields
mentioned in GROUP BY clause. Window Expression in ABAP SQL is similar in this
sense. However, it gives you individual records as well.
Windowing is a way to create partitions of the query result and perform various
operations on those partitions . The Window Expression is the expression that helps
you do this partition. Once the partition is done, you can apply window functions
on the partitions.
Let us consider an example. Say, you want to print price for a flight and also the
average price for same flight connection. Below is the data snapshot – for Carrier
AA and connection 0015, the average price is 2514 USD. You could get average using
aggregate function AVG, but you wont get individual records along with it.
What is the solution for this? WINDOW EXPRESSION AND WINDOW FUNCTIONS.
@AbapCatalog.sqlViewName: ‘ZSFLIGHTVIEW’
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘Flight Information’
@VDM.viewType: #BASIC
define view Zflight_View as select from sflight{
key sflight.carrid as AirlineCode,
key sflight.connid as ConnectionNumber,
key sflight.fldate as FlightDate,
sflight.price as Airfare,
sflight.currency as FareCurrency,
sflight.planetype as PlaneCategory,
sflight.seatsmax as MaxAvailableSeats,
sflight.seatsocc as OccupiedSeats
2)Create a CDS view similar to the above get the data from MARC table and display
the data for the below fields
3)
Inherited
Client Dependent
Client Indepenent
@AbapCatalog.sqlViewName: 'DEMO_CDS_PRJCTN0'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@ClientHandling.type: #CLIENT_DEPENDENT
@ClientHandling.algorithm: #AUTOMATED
define view demo_cds_spfli_client_0
as select from
spfli
{
key spfli.carrid,
key spfli.connid,
spfli.cityfrom,
spfli.cityto
}
4)Buffering Type
@AbapCatalog.sqlViewName: 'ZMAH_BUFF_04APR'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'CDS with Buffering'
@AbapCatalog.buffering.status: #ACTIVE
@AbapCatalog.buffering.type: #FULL
@AbapCatalog.sqlViewName: 'ZMAH_PARAM'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Example of parameter'
define view zmah_paramet_examp
with parameters carid : abap.char(3),
conid: s_conn_id
as select from spfli {
spfli.carrid,
spfli.connid,
spfli.countryfr,
spfli.countryto
}
where carrid = $parameters.carid and
connid = $parameters.conid
6)
@AbapCatalog.sqlViewName: 'ZV_CDS_TEST'
@AbapCatalog.compiler.CompareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'CDS Test View'
define view ZVA_CDS_TEST
as select from acdoca
left outer join kna1
on kna1.kunnr = acdoca.kunnr
left outer join makt
on makt.matnr = acdoca.matnr
left outer join adrc
on adrc.addrnumber = kna1.adrnr
{
acdoca.poper as poper,
acdoca.budat as budat,
acdoca.gjahr as gjahr,
acdoca.rbukrs as rbukrs,
acdoca.re_account as re_account,
kna1.erdat as erdat,
acdoca.matnr as matnr,
makt.maktx as maktx,
acdoca.kunnr as kunnr,
kna1.name1 as name1,
kna1.brsch as brsch,
kna1.adrnr as adrnr,
adrc.country as country,
acdoca.rtcur as rtcur,
acdoca.tsl as tsl,
adrc.date_to as date_to
} where
makt.spras = 'E' AND
8)Cast Expression
CAST is used to change the data types in CDS views. Data type changes are needed
for arithmetic calculation, for comparison during select or just to change the
display option for that field. It is important to note here that there are some
restrictions (more info here) on Casting one data type to another. Or can you?
key ekko.ebeln,
key ekpo.ebelp,
key eket.etenr,
ekpo.matnr,
ekpo.werks,
ekpo.lgort,
ekpo.meins,
ekpo.lmein,
9)
Extending a CDS View is a tool that can be utilized when editing the original CDS
view is not possible – either because of dependency or if it is SAP standard.
https://sapinaminute.com/extending-cds-view/
mtart as MaterialType,
meins as Uom
@AbapCatalog.sqlViewAppendName: 'ZFIRSTCDSE'
@EndUserText.label: 'Extending a CDS View'
extend view zfirstcds_mara with z000_Extend_zfirstcds_mara {
ersda as creationdate,
ernam as createdby
}
@AbapCatalog.sqlViewName: 'ZMAH_GRP_BY'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'CDS View Group By Example'
define view zmah_cds_grpby as select from
snwd_stock
join snwd_pd on snwd_stock.product_guid = snwd_pd.node_key
{
key snwd_pd.product_id,
snwd_pd.category,
// Aggregate function "SUM"
sum(snwd_stock.quantity) as total_stock
}
group by snwd_pd.category,
snwd_pd.product_id
@AbapCatalog.sqlViewName: 'ZMAH_CDSP'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'cds view with parameters'
define view demo_parameters_cds
/*Division*/
div(5,3) as Div_Op,
division(5,3,5) as Div_Op2,
mod(5,3) as Mod_Op,
a.price as Flg_Price,
round( a.price,1) as Round_Op
}
@AbapCatalog.sqlViewName: 'ZMAH_CDS_CASE'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'cds with case statement'
define view zmah_cds_21feb
with parameters p_date :abap.dats
@AbapCatalog.sqlViewName: 'ZMAH_BUFF_04APR'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'CDS with Buffering'
@AbapCatalog.buffering.status: #ACTIVE
@AbapCatalog.buffering.type: #FULL
@AbapCatalog.sqlViewName: 'ZMAH_ASSO'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'zmah_cds_associ_15_may_2023'
define view zmah_cds_associ_15_may_2023 as select from scarr
association[1..*] to spfli as _spfli
on $projection.carrid= _spfli.carrid {
key scarr.carrid as carrid,
scarr.carrname as carrname,
scarr.currcode as currcode,
_spfli
}
*&---------------------------------------------------------------------*
*& Report ZMAH_NEWSYNTAX_15_MAY_2023
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZMAH_NEWSYNTAX_15_MAY_2023.
public section.
interfaces IF_AMDP_MARKER_HDB.
class-methods get_flights for table function zmah_cds_tf.
protected section.
private section.
* FINAL
* CREATE PUBLIC .
*
* PUBLIC SECTION.
* PROTECTED SECTION.
* PRIVATE SECTION.
ENDCLASS.
WITH
+cities AS ( SELECT cityfrom AS city FROM spfli WHERE carrid = 'LH'
UNION DISTINCT
SELECT cityto AS city FROM spfli WHERE carrid = 'LH' )
SELECT * FROM sgeocity
WHERE city IN ( SELECT city FROM +cities )
INTO TABLE @DATA(result).
Earlier, to search for a text, you would get the data into internal table, loop
through the table, change the content of the field to be searched in to upper case,
also translate search string to upper case and then perform the ‘CS’ like
operation.
"Search string - this can be a parameter as well
DATA(search_string) = 'IRon'.
Operations like addition, subtraction and multiplication are allowed between fields
in the where clause.
ID
TEXT
001
One
002
Two
And here is a sample dataset from another imaginary database table Z2:
CODE
NAME
002
Two
016
Sixteen
019
Nineteen
Before the UNION command existed, we had to run two distinct queries to combine
this data into a single internal table.
SELECT
id AS key,
text AS value
FROM z1
INTO TABLE @DATA(lt_itab).
SELECT
code AS key,
name AS value
FROM z2
APPENDING CORRESPONDING FIELDS OF @lt_itab.
Now, UNION allows us to merge those queries.
SELECT
id AS key,
text AS value
FROM z1
UNION
code AS key,
name AS value
FROM z2
INTO TABLE @DATA(lt_itab).
Here is the catch: If we execute the UNION query above, we get the following
resultset:
@AbapCatalog.sqlViewName: 'ZSDFITDET'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@Analytics.dataCategory: #CUBE
@VDM.viewType: #COMPOSITE
@ObjectModel.usageType.serviceQuality: #D
@ObjectModel.usageType.sizeCategory : #XXL
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Fitter detailed Report'
define view ZSD_fitter_details
as select from
// Billing Documents
I_BillingDocumentBasic as _vbrk
inner join I_BillingDocumentItem as _vbrp on
_vbrk.BillingDocument = _vbrp.BillingDocument
// Sold-to-Party Address
inner join I_Customer as _kna1 on
_kna1.Customer = _vbrk.SoldToParty
// Document Flow
inner join I_SDDocumentMultiLevelProcFlow as _vbfa on
_vbfa.SubsequentDocument = _vbrk.BillingDocument
and
_vbfa.SubsequentDocumentItem = _vbrp.BillingDocumentItem
// Sales Order Header Details.
inner join I_SalesDocument as _vbak on
_vbak.SalesDocument = _vbfa.PrecedingDocument
inner join I_SalesDocumentItem as _vbap on
_vbap.SalesDocument = _vbak.SalesDocument
and
_vbap.SalesDocumentItem = _vbfa.PrecedingDocumentItem
// Business Data
inner join P_SalesDocumentBusinessData as _vbkd on
_vbkd.SlsDocBusinessData = _vbfa.PrecedingDocument
and
_vbkd.SlsDocBusinessDataItem is initial
// Condition Records: PPR0
inner join I_PricingElement as _prcdppr0 on
_prcdppr0.PricingDocument = _vbrk.PricingDocument
and
_prcdppr0.PricingDocumentItem = _vbrp.BillingDocumentItem
and
_prcdppr0.ConditionType = 'PPR0'
// Condition Records: ZRDI
left outer join I_PricingElement as _prcd_zrdi on
_prcd_zrdi.PricingDocument = _vbrk.PricingDocument
and
_prcd_zrdi.PricingDocumentItem = _vbrp.BillingDocumentItem
and
_prcd_zrdi.ConditionType = 'ZRDI'
left outer join I_BillingDocumentTypeText as _doctype_txt on
_doctype_txt.BillingDocumentType = _vbrk.BillingDocumentType
and
_doctype_txt.Language = $session.system_language
{
// Sales Organisation
_vbrk.SalesOrganization as
sales_org,
// Billing Document Type
_vbrk.BillingDocumentType as
bill_typ,
_doctype_txt.BillingDocumentTypeName as
bill_typ_txt,
// Creation Date
_vbrk.CreationDate as
cre_date,
// Creation Time
_vbrk.CreationTime as
cre_time,
// Sold to Party
_vbrk.SoldToParty as
cust_no,
// Customer Name
_kna1.CustomerName as
cust_name,
// Billing Document Date
_vbrk.BillingDocumentDate as
Bill_date,
// Period
concat( concat( substring( _vbrk.BillingDocumentDate, 5, 2 ), '/' ),
concat( substring( _vbrk.BillingDocumentDate, 1, 4 ), ' ' ) ) as period,
// Delivery Number
_vbrk.BillingDocument as del_no,
// _vbap.SalesDocument
as salesorder,
// _vbap.SalesDocumentItem
as salesitems,
// Delivery Item.
_vbrp.BillingDocumentItem as
line_no,
// Customer Reference
_vbkd.PurchaseOrderByCustomer as
cust_ref,
// Material
_vbrp.Material as
Material,
// Delivery Quantity
cast( _vbrp.BillingQuantity as abap.quan(13,0) ) as
quantity,
// Currency
_vbrp.TransactionCurrency as
currency,
// Conditional Amount : PPR0
@DefaultAggregation: #SUM
_prcdppr0.ConditionAmount as
fx_amount,
}
@AccessControl.authorizationCheck: #NOT_REQUIRED
@AbapCatalog.viewEnhancementCategory: [#PROJECTION_LIST]
@EndUserText.label: 'Further information about the CDS entity'