Semantic Parsing and Meaning Representations › Worked Examples: Logical Form, AMR, and SQL

Michael BrenndoerferMay 13, 20254 min read
Language AI HandbookAll chapters
Part 8 of 67Semantics and Information Extraction
Chapter 55Semantic Parsing and Meaning Representations › Worked Examples: Logical Form, AMR, and SQL
Reading section 8 of 13 · Worked Examples: Logical Form, AMR, and SQL · 4 minSection 8 of 13 · 4 min

Section 8 of 13 · 4 min read

Semantic Parsing and Meaning Representations › Worked Examples: Logical Form, AMR, and SQLSection view · Sections in this chapter8 / 13 ↓
Reading tools Definitions, links & notes

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Notes & comments

Let us make the differences concrete with a small schema and a few sentences.

The three utterances below highlight different strengths of the representation families: quantifier scope in logic, shared participants in AMR, and aggregation in SQL. They are separate examples rather than equivalent encodings of one sentence.

Logical Form and Scope

Take the sentence:

Every student reads a book.

A surface-scope logical form is:

∀x (student(x)→∃y (book(y)∧read(x,y)))\forall x \, (\text{student}(x) \to \exists y \, (\text{book}(y) \land \text{read}(x,y)))

An inverse-scope logical form is:

∃y (book(y)∧∀x (student(x)→read(x,y)))\exists y \, (\text{book}(y) \land \forall x \, (\text{student}(x) \to \text{read}(x,y)))

Both are consistent with the English string. The first says each student may read a different book. The second says there is one book that every student reads. A semantic parser that outputs one fully resolved, reading-specific logical form has made a choice. A system that needs to reason about ambiguity should represent both readings or defer the choice.

The executable example below constructs the surface-scope reading explicitly. A parser must resolve or retain the ambiguity according to its application; word order alone does not determine the intended scope.

AMR

Now take:

The boy wants to go.

An AMR graph is:

Code
CollapseExpand
(w / want-01
   :ARG0 (b / boy)
   :ARG1 (g / go-02
            :ARG0 b))

The graph contains a wanting node w, whose wanter is a boy b, and whose desired event is represented by a go-02 node g with the same boy as the understood goer. It does not assert that the boy actually goes. The reentrancy is explicit. The graph does not encode the difference between "the boy" and "a boy" in the same way first-order logic does. It abstracts over that distinction.

This is a feature for paraphrase stability: "The boy wants to go" and "A boy wants to go" receive very similar graphs, which is desirable if the task is about events and participants rather than definiteness.

Text-to-SQL

Suppose we have this schema:

SQL
CollapseExpand
departments(department_id, name)
students(student_id, name, department_id)
enrollments(student_id, course_id)

And this question:

Which departments have more than two enrolled students?

A correct SQL query is:

SQL
CollapseExpand
SELECT d.name
FROM departments AS d
JOIN students AS s
  ON s.department_id = d.department_id
JOIN enrollments AS e
  ON e.student_id = s.student_id
GROUP BY d.department_id, d.name
HAVING COUNT(DISTINCT e.student_id) > 2
ORDER BY d.name;

The query joins the three tables, groups by department, counts distinct enrolled students, and filters groups with more than two students. The DISTINCT matters if a student can appear in multiple enrollment rows. Without it, the count could overcount.

The query is not a flat lookup. Under the shown schema, it uses the department and enrollment relationships to identify which students to count. The graph displays these information dependencies; equivalent SQL need not use this exact join plan.

PythonIn [9]
CollapseExpand
join_nodes = {
    "departments": {"pos": (0.0, 0.0), "label": "departments"},
    "students": {"pos": (1.2, -0.8), "label": "students"},
    "enrollments": {"pos": (2.4, 0.0), "label": "enrollments"},
}
join_edges = [
    ("departments", "students", "department_id"),
    ("students", "enrollments", "student_id"),
]
VisualizationOut [10]
CollapseExpand
Join-path diagram connecting departments, students, and enrollments by key columns.
For the shown schema, the department question depends on the department_id relationship between departments and students and the student_id relationship between students and enrollments. Equivalent SQL can express these relationships without this exact join plan.

This example shows why text-to-SQL is not just translation. The question must be grounded in the schema, with its relationships and distinct-student count expressed correctly. The displayed solution uses joins and aggregation; equivalent SQL can use other structures. A fluent English paraphrase of the query is not enough.

It must also decide whether the count refers to distinct students or enrollment rows. Inner joins discard departments without matches before aggregation. Left joins can preserve them as zero-count groups, but this example's HAVING COUNT(DISTINCT e.student_id) > 2 excludes those groups under either join choice.

Comments

Add to the conversation

A question, a correction, or an example from your own work.

No comments yet. Be the first to share your thoughts!

Newsletter

Stay up to date

Get new articles, book updates, and notes on AI and technology.

Unsubscribe at any time. Privacy policy