41. How to send money amounts in JSON
Your payments API serves clients in India and the UAE. Which JSON shape for amounts is safest?
- A.{"amount": 1299.50} with the currency in the docs
- B.{"amount": "₹1,299.50"} as display text
- C.{"amount": 129950, "currency": "INR"} in minor units
- D.{"amount": 1299.5, "currency": "rupees"}
Show answer
Answer: C. {"amount": 129950, "currency": "INR"} in minor units
Integers in minor units (paise, fils) avoid floating-point errors, and an ISO 4217 code like INR or AED removes doubt about currency. Formatted text such as '₹1,299.50' is for display, not data. Some APIs instead send decimal strings like "1299.50" with a currency code, which is also safe.
42. Random UUID keys slow down inserts
A table uses random UUIDv4 primary keys. As it grows past RAM, insert throughput drops and WAL volume rises. What change helps most while keeping UUIDs?
- A.Use time-ordered UUIDs such as UUIDv7, so new keys go to the right edge of the B-tree
- B.Store the UUID as text instead of the uuid type
- C.Use a hash index for the primary key
- D.Increase max_connections
Show answer
Answer: A. Use time-ordered UUIDs such as UUIDv7, so new keys go to the right edge of the B-tree
Random keys insert into random leaf pages, so the working set is the whole index, with many cache misses, page splits and full page images in WAL. Time-ordered UUIDv7 keys append near the end like a sequence, keeping hot pages in memory. PostgreSQL 18 provides uuidv7(), and storing UUIDs as text would make things worse.
43. Pre-norm transformer blocks
Most modern large transformers put LayerNorm before each sub-layer (pre-norm) instead of after the residual add (post-norm). Why?
- A.It halves the parameter count
- B.Deep stacks train more stably
- C.It removes the need for residuals
- D.It makes attention linear in length
Show answer
Answer: B. Deep stacks train more stably
In pre-norm, the residual stream runs unchanged from input to output, so gradients pass cleanly through many layers. Post-norm puts a LayerNorm on the main path after every block, which tends to make very deep models unstable without careful warmup.
44. Monthly budget next to daily sales
Sales is daily by store; Budget is monthly by region. A developer related Sales directly to Budget and got many-to-many warnings and wrong totals. What is the better model?
- A.Merge Budget into Sales in Power Query by copying values
- B.Use bidirectional filters between Sales and Budget
- C.Divide the budget by 30 and store it per day
- D.Relate both facts to shared Date and Region dimensions
Show answer
Answer: D. Relate both facts to shared Date and Region dimensions
Each fact table should connect to shared dimensions, with Budget joined at its own grain (for example a month key and region). Visuals by month and region then show both, and DAX can hide budget when users drill below month. Linking facts directly creates ambiguous many-to-many paths.
45. End dates for history rows
A customer address history has valid_from dates only. How do you fill valid_to for a type 2 dimension?
- A.LAG(valid_from) per customer by date, minus one day; NULL means current
- B.MAX(valid_from) per customer, so every version ends on the latest date
- C.LEAD(valid_from) per customer by date, minus one day; NULL means current
- D.valid_from plus one year for every version, capped at today's date
Show answer
Answer: C. LEAD(valid_from) per customer by date, minus one day; NULL means current
Each version ends the day before the next version starts, and LEAD gives the next start within the same customer. The current version has no next row, so LEAD is NULL, which you leave open or set to a far-future date such as 9999-12-31. Two versions starting on the same date must be cleaned first or one gets a negative range.
46. Double counting in an SCD2 join
dim_customer has two versions for customer 7: Dubai valid 2026-01-01 to 2026-05-01, and Abu Dhabi valid 2026-05-01 to 9999-12-31. Facts: an order on 2026-03-10 (50) and one on 2026-05-01 (100). What SUM(amount) does this query return?
SELECT SUM(f.amount)
FROM fact_orders f
JOIN dim_customer d
ON f.customer_id = d.customer_id
AND f.order_date BETWEEN d.valid_from AND d.valid_to;
- A.150
- B.100
- C.250
- D.200
Show answer
Answer: C. 250
BETWEEN is inclusive on both ends, so the 2026-05-01 order matches both the version ending on 05-01 and the one starting on 05-01, and its 100 is counted twice: 50 + 100 + 100 = 250. Use a half-open range, order_date >= valid_from AND order_date < valid_to, or better, store the surrogate key on the fact at load time.
47. 3NF but not BCNF
In enrolments(student, subject, teacher), each teacher teaches exactly one subject, and a student takes each subject from one teacher. The key is (student, subject). What is its normal form?
- A.3NF but not BCNF
- B.Not in 1NF
- C.BCNF
- D.Not in 2NF
Show answer
Answer: A. 3NF but not BCNF
teacher → subject holds, but teacher is not a superkey, so BCNF fails. Every column is part of some candidate key ((student, subject) or (student, teacher)), so 2NF and 3NF are met. Splitting into (teacher, subject) and (student, teacher) reaches BCNF.
48. Attributes that change every month
dim_customer has 50 million rows. Income band and loyalty tier change monthly for many customers, and type 2 tracking would explode the table. What design handles this?
- A.Switch the whole customer dimension to type 1 updates
- B.Add one column per month for each changing attribute
- C.Keep those attributes only in the source CRM system
- D.Move them into a mini-dimension keyed on the fact
Show answer
Answer: D. Move them into a mini-dimension keyed on the fact
A mini-dimension holds the distinct combinations of volatile attributes, such as band × tier, which is a small table. The fact gets a second key that records the combination at event time. History is kept without creating a new 50-million-row version each month.
49. Shipping charge counted three times
An order has three lines and one ₹90 shipping charge. The ETL copied ₹90 onto each line in fact_order_lines. Revenue reports now show ₹270 of shipping. What is the proper fix?
- A.Allocate the charge across lines, or keep a header-level fact
- B.Divide every shipping total by the order count
- C.Report only the MAX shipping per order everywhere
- D.Remove shipping from the warehouse
Show answer
Answer: A. Allocate the charge across lines, or keep a header-level fact
This is a grain mismatch: a header-level fact was placed on a line-level table. Either allocate the ₹90 across lines (for example by value, so the parts add to ₹90), or keep header facts in their own table. Fixes in reports like MAX are fragile and easy to forget.
50. Weights in a joint account bridge
A joint bank account with a balance of AED 10,000 has two holders. It links to dim_customer through a bridge table with a weight of 0.5 for each holder. What do the weights achieve?
- A.Each holder shows AED 10,000, the full balance
- B.The account is hidden until weights add to 2
- C.Each holder shows AED 5,000, so the total stays AED 10,000
- D.Only the first holder gets the balance
Show answer
Answer: C. Each holder shows AED 5,000, so the total stays AED 10,000
Without weights, grouping by customer gives each holder AED 10,000 and the grand total becomes AED 20,000. Allocating by a weighting factor that sums to 1 per account keeps totals correct. You can still report unweighted "impact" figures when needed.
51. Product specs as attribute rows
To support any product spec, a team stores specs as rows: (product_id, attribute_name, value), with value as text. What is the main cost of this design?
- A.It cannot store more than 100 attributes
- B.No real types or constraints, and queries need pivots
- C.It makes adding a new attribute need a migration
- D.Rows in the table can never be indexed
Show answer
Answer: B. No real types or constraints, and queries need pivots
Entity–attribute–value is flexible, but every value is text, so the database cannot check types, required fields or ranges. Simple questions need self-joins or pivots, and reports get slow and messy. A JSON column with validation, or proper columns for common specs, is often better.
52. Reprinted invoice shows a new price
order_lines stores product_id and qty, and invoices join to products.price. After a price rise, last month's reprinted invoices show the new price. What is the right model?
- A.Store the unit price on each order line at sale time
- B.Never allow product prices to change
- C.Recalculate old invoices with a discount
- D.Keep only one product price per year
Show answer
Answer: A. Store the unit price on each order line at sale time
The price paid is a fact about the sale, not about the product, so it must be copied onto the order line when the order is placed. This is deliberate, not a normalisation failure: the values mean different things. A separate price history table can also answer "what was the list price on a date".
53. is_weekend for UAE dates
From January 2022 the UAE moved its official weekend from Friday–Saturday to Saturday–Sunday. How should your date dimension's is_weekend flag handle this?
- A.Use Saturday–Sunday for all dates
- B.Use Friday–Saturday for all dates
- C.Set it per date using the rule in force on that date
- D.Compute it in each report from the weekday
Show answer
Answer: C. Set it per date using the rule in force on that date
Calendar attributes can change over time, and a date dimension should store the value that was true for each date. Old dates keep Friday–Saturday weekends, newer ones use Saturday–Sunday. One fixed rule would misclassify years of history and break weekday-vs-weekend comparisons.
54. Hash diff misses some changes
A hash diff is built as MD5(first_name || last_name || city). Some real changes are never detected, and some rows hash to NULL. What is the fix?
- A.Use SHA-256 instead of MD5
- B.COALESCE each column and join them with a delimiter
- C.Sort the columns alphabetically before concatenating
- D.Hash only the primary key
Show answer
Answer: B. COALESCE each column and join them with a delimiter
In SQL, concatenating any NULL gives NULL, so those rows always look unchanged. Without a delimiter, "ab"+"c" and "a"+"bc" give the same string and the same hash. Replace NULLs with a marker and put a separator such as '|' between columns; a stronger hash fixes neither problem.
55. Why Data Vault 2.0 uses hash keys
Data Vault 2.0 replaced sequence surrogate keys with hashes of business keys in hubs and links. What is the main benefit?
- A.Hashes make business keys unnecessary
- B.Hash keys remove the need for satellites
- C.Hubs, links and satellites can load in parallel without lookups
- D.They stop duplicate business keys arriving from source systems
Show answer
Answer: C. Hubs, links and satellites can load in parallel without lookups
With sequences, a link or satellite load must first look up the hub's generated key, which forces a load order. A hash of the business key can be computed by every job independently, so all tables can load at the same time. It also works across platforms that have no shared sequence.
56. Storing money as integer fils
A payments table stores amounts as integers in minor units, assuming 100 minor units per currency. It works for AED and INR. What breaks when Kuwait goes live?
- A.KWD has 1,000 fils per dinar, so amounts are off by ten
- B.KWD cannot be stored as an integer at all
- C.Kuwait has no minor unit, so values are too large
- D.Nothing; every currency uses 100 minor units
Show answer
Answer: A. KWD has 1,000 fils per dinar, so amounts are off by ten
Currencies differ in decimal places: AED and INR use 2, while KWD, BHD and OMR use 3, and JPY uses 0. A fixed divide-by-100 rule reads 1,500 fils as 15 KWD instead of 1.5. Store the currency code and use a per-currency exponent from a reference table.
57. Two tables that reference each other
departments.head_emp_id references employees, and employees.dept_id references departments, both NOT NULL. You cannot insert the first department or employee. What PostgreSQL feature helps?
- A.ON DELETE CASCADE on both foreign keys
- B.DEFERRABLE INITIALLY DEFERRED foreign keys
- C.A UNIQUE constraint on head_emp_id
- D.Disabling the primary keys during inserts
Show answer
Answer: B. DEFERRABLE INITIALLY DEFERRED foreign keys
Normally a foreign key is checked after each statement, so the first row of a cycle always fails. A deferred constraint is checked when the transaction commits, so you can insert both rows and then commit. Another option is to make one side nullable and fill it in after.
58. A product moved to a new category
A product moved from "Home" to "Kitchen" in June. Finance wants last year's category totals to stay as reported, but merchandising wants all history under today's category. What design serves both?
- A.Type 2 history plus a current-category column on each row
- B.Type 1 overwrite of the category
- C.Type 2 history only, with no current-category attribute
- D.Two separate warehouses, one built for each team
Show answer
Answer: A. Type 2 history plus a current-category column on each row
Type 2 rows keep the category valid at each sale, so finance's "as was" totals stay stable. Adding a current_category column, updated on every row of the product (a type 6 hybrid), gives merchandising the "as is" view. Each team then chooses the column that answers its question.
59. Building blocks of Data Vault
A bank models its integration layer with Data Vault 2.0. What are hubs, links and satellites?
- A.Hubs store reports, links store dashboards, satellites store users
- B.Business keys, relationships, and attributes over time
- C.Hubs are facts, links are dimensions, satellites are aggregates
- D.Hubs are raw files, links are views, satellites are backups
Show answer
Answer: B. Business keys, relationships, and attributes over time
Hubs list unique business keys such as customer numbers. Links record relationships between hubs, such as customer-to-account. Satellites hold descriptive attributes with load timestamps, keeping full history. The model handles many changing sources well, and star schemas are usually built on top for reporting.
60. Students, courses and grades
Students take many courses, each course has many students, and you need to store the enrolment date and final grade. What is the best data model?
- A.Add grade and date columns to the Student table
- B.Store a comma-separated list of courses in each student row
- C.An associative entity, such as Enrolment, between Student and Course that holds the date and grade
- D.Link Course to Student as one-to-many
Show answer
Answer: C. An associative entity, such as Enrolment, between Student and Course that holds the date and grade
A many-to-many relationship is resolved with a linking entity that has a foreign key to each side. Attributes of the relationship itself, like the grade, belong there. Lists in one column break normalisation and make queries painful.