5.2 Built-in SQL Expressions and an Integrated Query

Key Takeaways

  • concat and concat_ws have different null behavior; choose the one required by the output contract.

  • SQL substring is one-based; a split array is indexed differently by bracket access.

  • CASE WHEN evaluates branches and COALESCE chooses a non-null fallback; these functions do not change missing-data business policy.

  • Date parsing depends on the pattern and ANSI/parser settings; retain raw input when investigating failed conversions.

Last updated: October 2026

4. Built-in SQL Functions and Expressions

Spark SQL provides hundreds of optimized built-in functions. Built-in functions expose expression semantics to Spark and often execute efficiently in JVM/vectorized paths. Code generation support and performance depend on the specific function; arbitrary Python UDF logic is opaque to Catalyst.

String Manipulation Functions

FunctionSyntaxDescription & Exam Considerations
concatconcat(col1, col2, ...)Concatenates strings. Returns NULL if ANY argument is NULL.
concat_wsconcat_ws(sep, col1, col2, ...)Concatenates strings with a delimiter. Skips NULL inputs automatically.
substringsubstring(str, pos, len)Extracts substring. 1-based index! pos = 1 starts at the first character. Negative pos counts from the end.
trim / ltrim / rtrimtrim(str); SQL also supports TRIM(BOTH chars FROM str)Strips leading/trailing whitespace or designated characters.
splitsplit(str, regex [, limit])Splits string by regex pattern into an ArrayType[StringType].
upper / lowerupper(str), lower(str)Converts characters to uppercase or lowercase.
lengthlength(str)Returns the character count of the string.
initcapinitcap(str)Capitalizes the first letter of each word in the string.
regexp_replaceregexp_replace(str, regex, rep)Replaces occurrences matching regex with replacement string.
SELECT 
    concat_ws(' ', first_name, last_name) AS full_name,
    substring(postal_code, 1, 3) AS postal_district,
    split(email, '@')[1] AS email_domain
FROM sales.customers;

Date and Timestamp Functions

Spark SQL date math assumes calendar standards (ISO 8601) and supports microsecond timestamp precision:

FunctionSyntaxReturn TypeDescription
current_datecurrent_date()DATECurrent date evaluated at query start.
current_timestampcurrent_timestamp()TIMESTAMPCurrent date and time evaluated at query start.
to_dateto_date(col [, fmt])DATEParses string to DateType using optional pattern (e.g. 'yyyy-MM-dd'). Invalid-input behavior depends on ANSI mode and parsing policy; use tolerant parsing when required.
to_timestampto_timestamp(col [, fmt])TIMESTAMPParses string to TimestampType. Invalid-input behavior depends on ANSI mode and parsing policy; use tolerant parsing when required.
date_adddate_add(startDate, numDays)DATEAdds integer days to a date.
date_subdate_sub(startDate, numDays)DATESubtracts integer days from a date.
datediffdatediff(endDate, startDate)INTCalculates endDate - startDate in days. Positive if endDate > startDate.
months_betweenmonths_between(endDate, startDate [, roundOff])DOUBLECalculates number of months between dates. Positive if endDate > startDate.
date_truncdate_trunc(format, timestamp)TIMESTAMPTruncates timestamp to specified unit: 'year', 'month', 'day', 'hour', 'minute'.
year / month / dayyear(col), month(col), dayofmonth(col)INTExtracts date component as an integer.
SELECT 
    order_id,
    order_date,
    date_add(order_date, 30) AS payment_due_date,
    datediff(current_date(), order_date) AS days_since_order,
    date_trunc('month', order_date) AS order_month
FROM sales.orders;

Conditional Expressions and Null Handling

Spark SQL supports standard ANSI branching expressions and null substitution primitives:

  • CASE WHEN: Standard multi-branch conditional evaluation.
    CASE 
        WHEN order_amount >= 1000 THEN 'Platinum'
        WHEN order_amount >= 500  THEN 'Gold'
        WHEN order_amount >= 100  THEN 'Silver'
        ELSE 'Standard'
    END AS customer_tier
    
  • COALESCE(expr1, expr2, ...): Evaluates arguments from left to right and returns the first non-null expression. If all arguments are null, returns NULL.
  • NVL(expr1, expr2): Two-argument shorthand equivalent to COALESCE(expr1, expr2). If expr1 is null, returns expr2.
  • IF(condition, true_val, false_val): Functional ternary branch. Returns true_val if condition evaluates to true; otherwise returns false_val.
  • NULLIF(expr1, expr2): Returns NULL if expr1 == expr2; otherwise returns expr1.
  • NANVL(expr1, expr2): Used for floating-point columns. Returns expr2 if expr1 is NaN (Double.NaN or Float.NaN); otherwise returns expr1.

5. End-to-End Production Scenario Walkthrough

Consider an enterprise e-commerce platform that needs to compute customer loyalty risk tiers. The query must identify high-value customers, compute their days since last purchase, handle missing contact info, and flag inactive accounts:

WITH 
    -- Step 1: Clean transactions and filter for valid sales
    valid_sales AS (
        SELECT 
            order_id,
            customer_id,
            order_amount,
            to_date(order_timestamp) AS order_date
        FROM ecommerce.orders
        WHERE order_status = 'DELIVERED'
    ),
    -- Step 2: Compute per-customer aggregates
    customer_metrics AS (
        SELECT 
            customer_id,
            COUNT(order_id) AS total_orders,
            SUM(order_amount) AS total_revenue,
            MAX(order_date) AS latest_order_date
        FROM valid_sales
        GROUP BY customer_id
    ),
    -- Step 3: Identify VIP threshold using a scalar subquery
    vip_threshold AS (
        SELECT AVG(total_revenue) * 1.5 AS threshold_val
        FROM customer_metrics
    )
-- Final Step: Join with customer catalog and assign operational flags
SELECT 
    c.customer_id,
    concat_ws(' ', c.first_name, c.last_name) AS customer_name,
    COALESCE(c.phone_number, 'NOT_PROVIDED') AS contact_phone,
    cm.total_orders,
    round(cm.total_revenue, 2) AS total_revenue,
    cm.latest_order_date,
    datediff(current_date(), cm.latest_order_date) AS days_inactive,
    CASE 
        WHEN cm.total_revenue >= (SELECT threshold_val FROM vip_threshold) THEN 'VIP Tier'
        WHEN cm.total_orders >= 5 THEN 'Loyal Regular'
        ELSE 'Standard Customer'
    END AS loyalty_segment,
    IF(datediff(current_date(), cm.latest_order_date) > 90, 'CHURN_RISK', 'ACTIVE') AS risk_status
FROM customer_metrics cm
JOIN ecommerce.customers c ON cm.customer_id = c.customer_id
WHERE c.customer_id NOT IN (
    -- Filter out test and internal accounts, ensuring NULLs are excluded
    SELECT customer_id FROM ecommerce.internal_test_accounts WHERE customer_id IS NOT NULL
)
ORDER BY cm.total_revenue DESC;
Test Your Knowledge

Which expression joins first_name and last_name with a space while skipping null name arguments?

A

concat(first_name, last_name)

B

split(first_name, last_name)

C

coalesce(first_name, last_name)

D

concat_ws(' ', first_name, last_name)

Sections you finish are checked off in the contents.