Appearance
Lesson 4 Practice — Booking Details with CDS Joins
The guided lesson combined:
text
Connection
Carrier
Origin Airport
Destination Airportinto one route model.
In this practice, solve a different relational problem:
A booking stores IDs for a customer and carrier. Build a CDS model that exposes useful booking details together with the related customer and carrier information.
Your architecture will be:
text
/DMO/CUSTOMER ──┐
│
/DMO/BOOKING ────┼──→ ZI_BOOKING_DETAIL_###
│
/DMO/CARRIER ────┘
↓
Booking Reader
↓
RunnerThe complete solution is intentionally not included here.
Objects to create
text
ZI_BOOKING_DETAIL_###
ZCL_BOOKING_READER_###
ZCL_CDS_L04_PRACTICE_###Replace ### with your own student/group suffix.
Part 1 — Inspect /DMO/BOOKING
Open:
text
/DMO/BOOKINGwith:
text
Ctrl + Shift + AIdentify:
text
travel_id
booking_id
booking_date
customer_id
carrier_id
connection_id
flight_date
flight_price
currency_codeConfirm that the booking key is:
text
travel_id + booking_idOpen Data Preview.
Record:
text
one Customer ID:
one Carrier ID:from a booking row.
Part 2 — Inspect /DMO/CUSTOMER
Open:
text
/DMO/CUSTOMERFind:
text
customer_id
first_name
last_nameFind the customer ID you recorded.
Record:
text
First name:
Last name:Part 3 — Inspect /DMO/CARRIER
Open:
text
/DMO/CARRIERFind:
text
carrier_id
name
currency_codeFind the carrier ID you recorded.
Record:
text
Carrier name:Part 4 — Design the result model
Your CDS entity must expose:
text
TravelId
BookingId
BookingDate
CustomerId
CustomerFirstName
CustomerLastName
CustomerName
CarrierId
CarrierName
ConnectionId
FlightDate
FlightPrice
CurrencyCodeCustomerName should be calculated from:
text
first name + one space + last nameusing the CDS expression skills from Lesson 3.
Part 5 — Draw the relationships
Complete:
text
Booking.customer_id
↓
____________________.____________________
Booking.carrier_id
↓
____________________.____________________Then answer:
Do the target fields identify the corresponding target records?
Part 6 — Create the Data Definition
Create:
text
ZI_BOOKING_DETAIL_###Description:
text
Lesson 4 - Booking DetailChoose a CDS View Entity template.
Use:
text
/DMO/BOOKINGas the primary source with alias:
text
BookingPart 7 — Join Customer
Join:
text
/DMO/CUSTOMERwith alias:
text
CustomerUse:
text
INNER JOINThe ON condition must match the booking's customer ID to the customer record.
Hint
The shape is:
abap
inner join /dmo/customer as Customer
on Booking.__________ = Customer.__________Part 8 — Join Carrier
Join:
text
/DMO/CARRIERwith alias:
text
CarrierUse:
text
INNER JOINThe ON condition must connect the booking's carrier ID with the carrier key.
Part 9 — Define the CDS keys
The CDS entity represents:
text
a bookingMark as keys only the elements needed to identify a booking.
Do not mark these as keys:
text
CustomerName
CarrierName
FlightPricePart 10 — Expose customer information
Expose:
text
CustomerId
CustomerFirstName
CustomerLastNameUse qualified source references:
text
Booking.<field>
Customer.<field>Make the data source of each element obvious.
Part 11 — Calculate CustomerName
Use:
text
CONCAT_WITH_SPACEThe result should resemble:
text
Jane Smithrather than:
text
JaneSmithHint
The shape is:
abap
concat_with_space(
Customer.__________,
Customer.__________,
1
) as CustomerNamePart 12 — Expose carrier and booking details
Expose:
text
CarrierId
CarrierName
ConnectionId
FlightDate
FlightPrice
CurrencyCodeCarrierName must come from:
text
CarrierPart 13 — Syntax check and activate
Run:
text
Ctrl + F2Fix all errors.
Activate:
text
Ctrl + F3Preview:
text
F8Part 14 — Verify one joined row
Choose one booking result.
Compare:
text
CustomerId
CustomerName
CarrierId
CarrierNamewith the independent Data Preview results of:
text
/DMO/CUSTOMER
/DMO/CARRIERRecord:
text
Travel ID:
Booking ID:
Customer match verified: Yes / No
Carrier match verified: Yes / NoPart 15 — Check for row multiplication
Inspect whether the same:
text
TravelId + BookingIdappears unexpectedly more than once.
If it does:
- inspect the target keys;
- inspect the
ONconditions; - determine whether one booking is matching several target rows.
Do not immediately add:
text
DISTINCTAnswer:
Why can an incomplete join condition produce several rows for one source record?
Part 16 — SQL Console
Query:
text
ZI_BOOKING_DETAIL_###Return at least:
text
TravelId
BookingId
CustomerName
CarrierId
CarrierName
ConnectionId
FlightDate
FlightPrice
CurrencyCodeOrder by:
text
TravelId
BookingIdPart 17 — Filter by carrier
Use the carrier ID recorded in Part 1.
Add a SQL Console filter for:
text
CarrierIdConfirm that every result row belongs to that carrier.
Part 18 — Create the Booking Reader
Create:
text
ZCL_BOOKING_READER_###The Reader should not implement:
text
IF_OO_ADT_CLASSRUNDefine:
text
TT_BOOKINGSas a standard table based directly on:
text
ZI_BOOKING_DETAIL_###with:
text
WITH EMPTY KEYPart 19 — Add GET_ALL
Create:
text
GET_ALLRequirements:
- return
TT_BOOKINGS; - select from
ZI_BOOKING_DETAIL_###; - use
FIELDS *; - order by
TravelId,BookingId; - contain no direct Customer or Carrier join syntax.
Part 20 — Add GET_BY_CARRIER
Create:
text
GET_BY_CARRIERImport:
text
carrier_idReturn:
text
TT_BOOKINGSRequirements:
- select from
ZI_BOOKING_DETAIL_###; - filter on CDS element
CarrierId; - use an ABAP SQL host variable;
- order by
TravelId,BookingId.
Part 21 — Create the Runner
Create:
text
ZCL_CDS_L04_PRACTICE_###Implement:
text
IF_OO_ADT_CLASSRUNIn main:
- instantiate the Booking Reader;
- call
GET_ALL; - loop over the result;
- display a readable line containing:
text
TravelId/BookingId
CustomerName
CarrierNameDesign the exact output yourself.
Part 22 — Test GET_BY_CARRIER
Use a carrier ID present in the current tenant.
Call:
text
GET_BY_CARRIERDisplay the returned bookings.
Confirm:
text
Reader
↓
ZI_BOOKING_DETAIL_###and not:
text
Reader
↓
direct Customer/Carrier joinsPart 23 — Explain INNER JOIN
In your own words:
What happens to a booking if its customer_id has no matching /DMO/CUSTOMER row?
What happens to a booking if its carrier_id has no matching /DMO/CARRIER row?
Part 24 — Think about LEFT OUTER JOIN
Without changing your final solution yet, answer:
If the Customer join changed to LEFT OUTER JOIN, what would happen to a booking with no matching Customer row?
What would happen to the Customer-side values at SQL level?
Would changing only the Customer join change the Carrier join's behavior?
Part 25 — Join-type experiment
Make a temporary copy or temporary edit.
Change:
text
Customer INNER JOINto:
text
Customer LEFT OUTER JOINActivate and preview.
Then restore your intended final version.
If the visible result does not change, explain why complete demo reference data can make the two previews look the same even though the join semantics differ.
Part 26 — Reasoning questions
Answer in your own words.
1. What problem does a join solve?
2. What is the purpose of an ON condition?
3. Why should target keys be inspected before writing a join?
4. Why are TravelId and BookingId still the keys of the joined model?
5. Why is CustomerName not a key?
6. Why does CarrierName come from /DMO/CARRIER?
7. What is the difference between INNER JOIN and LEFT OUTER JOIN?
8. How can one source row become several result rows?
9. Why should unexpected duplicates be investigated before using DISTINCT?
10. Why is the Reader simpler after the join is modeled in CDS?
11. Why are meaningful aliases useful?
12. Why will associations be useful after learning joins?
Optional challenge 1 — Customer location
Expose:
text
CustomerCity
CustomerCountryfrom /DMO/CUSTOMER.
Filter the joined CDS entity in SQL Console by a country present in your data.
Optional challenge 2 — Add Connection
Join:
text
/DMO/CONNECTIONto the booking model.
Before coding, inspect its key:
text
carrier_id
connection_idYour ON condition must represent the complete relationship.
Expose:
text
DepartureTime
ArrivalTimeThen answer:
What could happen if you joined only on
connection_idand ignoredcarrier_id?
Hint
A complete relationship needs both booking fields that identify the connection.
Submission checklist
Useful ADT shortcuts
| Action | Shortcut |
|---|---|
| Open ABAP Development Object | Ctrl + Shift + A |
| Code completion | Ctrl + Space |
| Syntax check | Ctrl + F2 |
| Activate current object | Ctrl + F3 |
| Activate inactive objects | Ctrl + Shift + F3 |
| CDS Data Preview | F8 |
| Run console class | F9 |
| Format source | Shift + F1 |