Coding questions · Amazon
Explain MySQL to MS SQL Server query syntax differences.
This question evaluates a candidate's understanding of SQL dialect differences between MySQL and MS SQL Server — including alias scope, CTE structure, ordering semantics, and lexical range comparisons that affect query portability and correctness.
transactions
| id | user_id | amount | txn_date |
|---|---|---|---|
| 1 | 1001 | 25.00 | 2023-07-01 |
| 2 | 1002 | 40.00 | 2023-07-02 |
| 3 | 1001 | 15.00 | 2023-07-03 |
| 4 | 1003 | 60.00 | 2023-07-03 |
| 5 | 1001 | 30.00 | 2023-07-04 |
Scenario
You are migrating analytics queries from MySQL to MS SQL Server and need to verify candidates understand subtle syntax differences, CTE structure, aliases, ordering and equivalence of filtering clauses.
Question
In MySQL the query
SELECT id, COUNT(*) AS transactions
FROM transactions
GROUP BY id
HAVING transactions > 10;
runs, but the same fails in MS SQL Server. Explain why and rewrite a version portable to both engines.
What does the statement "SELECT * FROM A B;" do and why can it be legal SQL?
Given ORDER BY id, ORDER BY id ASC and ORDER BY id DESC, which one produces a different ordering and why?
Provide the correct multi-CTE skeleton that defines two CTEs, A and B, then queries them.
Will the following three predicates return identical rows for a char column containing only upper-case letters? Justify.
a) col IN ('A','B','C')
b) col BETWEEN 'A' AND 'C'
c) col >= 'A' AND col <= 'C'
Hints
Focus on alias scope rules, default sort order, comma vs alias syntax, WITH clause commas, and lexical range comparisons.
MySQL vs SQL Server Syntax Differences and Multi-CTE Usage
You are migrating analytics queries from MySQL to Microsoft SQL Server and need to verify understanding of cross‑engine SQL syntax details.
Using the transactions table below:
-
In MySQL, the query
SELECT id, COUNT(*) AS transactions FROM transactions GROUP BY id HAVING transactions > 10;runs, but it fails in SQL Server. Explain why, and rewrite a version that is portable to both MySQL and SQL Server.
-
Explain what the statement SELECT * FROM A B; does and why it can be legal SQL. Clarify how it differs from SELECT * FROM A, B;.
-
Given ORDER BY id, ORDER BY id ASC, and ORDER BY id DESC, which one produces a different ordering and why? State the default sort direction.
-
Provide the correct multi‑CTE skeleton that defines two CTEs, A and B, then queries them in a final SELECT (you may use the transactions table to illustrate).
-
For a CHAR(1) column containing only upper‑case letters, will the following predicates return identical rows? Justify your answer. a) col IN ('A','B','C') b) col BETWEEN 'A' AND 'C' c) col >= 'A' AND col <= 'C'
Write a single SQL script that includes: (i) the portable version of the aggregation query from part (1), and (ii) a concrete multi‑CTE example that computes, per user_id, both the number of transactions and the total transaction amount using two CTEs A and B.
Table transactions
| column | type | constraints |
|---|---|---|
| id | INTEGER | PRIMARY KEY, NOT NULL |
| user_id | INTEGER | NOT NULL |
| amount | DECIMAL(10,2) | NOT NULL |
| txn_date | DATE | NOT NULL |
Sample data:
| amount | id | txn_date | user_id |
|---|---|---|---|
| 25 | 1 | 2023-07-01 | 1001 |
| 40 | 2 | 2023-07-02 | 1002 |
| 15 | 3 | 2023-07-03 | 1001 |
| 60 | 4 | 2023-07-03 | 1003 |
| 30 | 5 | 2023-07-04 | 1001 |
Expected output
Conceptually, the candidate should explain and demonstrate:
- MySQL allows referring to a SELECT-list alias (transactions) in HAVING, but SQL Server does not; T-SQL requires the aggregate expression itself (e.g., HAVING COUNT() > 10), or a wrapping subquery. A portable query repeats COUNT() in HAVING instead of using the alias.
- SELECT * FROM A B; selects from table A and gives it the table alias B (equivalent to SELECT * FROM A AS B). It is not a join; a comma would be required to introduce another table (SELECT * FROM A, B; is a cross join of A and B).
- ORDER BY id and ORDER BY id ASC are identical because ASC is the default sort direction. ORDER BY id DESC is the one that produces the opposite ordering (descending). Null placement may vary by engine/settings, but ASC is the default in both MySQL and SQL Server.
- Multiple CTEs share a single WITH keyword and are separated by commas, for example: WITH A AS (...), B AS (...) SELECT ... FROM A JOIN B ...; In SQL Server, the previous statement must be properly terminated (typically with a semicolon) before WITH.
- For a CHAR(1) column with only uppercase letters, col IN ('A','B','C'), col BETWEEN 'A' AND 'C', and col >= 'A' AND col <= 'C' all return the same rows because BETWEEN is inclusive and comparisons are lexical; the only values in the domain between 'A' and 'C' (inclusive) are 'A', 'B', and 'C'. For multi-character strings or a broader domain, BETWEEN/range predicates can include other values (e.g., 'AA', 'BA', 'CA'), so they would not be equivalent to IN.
For the concrete multi-CTE example, the final SELECT should return one row per user_id with the count of transactions and the total amount, as shown below.
| total_amount | txn_count | user_id |
|---|---|---|
| 70 | 3 | 1001 |
| 40 | 1 | 1002 |
| 60 | 1 | 1003 |
Hints
- In SQL Server, a HAVING clause cannot reference a SELECT-list alias; repeat the aggregate or wrap the query in an outer SELECT.
- SELECT * FROM A B means: select from table A, giving it alias B; spaces introduce aliases, while commas introduce additional tables (joins).
- ASC is the default sort direction; only DESC changes the ordering.
- Multiple CTEs are defined after a single WITH and are comma-separated; in SQL Server, terminate the prior statement (e.g., with a semicolon) before WITH.
- BETWEEN is inclusive and uses lexical comparison; with CHAR(1) uppercase letters, IN ('A','B','C'), BETWEEN 'A' AND 'C', and the equivalent range predicate match the same set, but this may differ for longer strings.