1

I'm working on the SELECT clause for the VALUES section of an SQL INSERT statement. One of the fields of the record is a foreign key to a table of foreign keys to other records.

Given: Table - Ing_Fundamental

+----------------+-------------------+  
| ID_Fundamental | ID_Title_Category |  
+----------------+-------------------+  

Table - Title_Category

+-------------------+----------+-------------+  
| ID_Title_Category | ID_Title | ID_Category |  
+-------------------+----------+-------------+  

Table - Titles

+----------+-------+  
| ID_Title | Title |  
+----------+-------+  

Table - Categories

+-------------+----------+  
| ID_Category | Category |  
+-------------+----------+  

I want to select the ID_Title_Category field where Titles.Title = "Hamburger" and Categories.Category = "Meat".

My SQL INSERT statement:

INSERT INTO Ing_Fundamental
(
    Ing_Fundamental.ID_Title_Category
)
VALUES
(
   (SELECT ????)
)

Here's the SQL CREATE TABLE statement for Ing_Fundamental:

CREATE TABLE IF NOT EXISTS Ing_Fundamental
(
    ID_Fundamental INTEGER UNSIGNED PRIMARY KEY AUTO_INCREMENT NOT NULL,
    ID_Title_Category INTEGER UNSIGNED,
    FOREIGN KEY fk_ID_Title_Category(ID_Title_Category)
       REFERENCES ing_title_categories(ID_Title_Category)
       ON UPDATE CASCADE
       ON DELETE RESTRICT,
    UNIQUE(ID_Title_Category)
)

My attempt at the SELECT statement is:

(SELECT Ing_Title_Categories.ID_Title_Category  
 FROM Ing_Title_Categories  
 WHERE (ID_Title_Category = 0))

But the above statement isn't going to work correctly because the ID_Title_Category field value is not correct, it must be determined by looking up values in the Titles and Categories tables.

So, what is the SQL syntax for selecting the ID_Title_Category field based on the fields in the Titles and Categories tables?

Edit 1: background / design
A fundamental ingredient has a unique ID.
A fundamental ingredient has a title and a category.
Categories are fixed (limited).

A User wants to search the database for an ingredient based on a title and a category.

A recipe contains one or more ingredients (ingredient IDs).

I don't remember my justification for the Title_Category table; It could either be normalization or reduce the need for a compound primary key.

I'm writing an application in C++ to interact with the database via SQL statements and queries.

In programming terminology:
The Ing_Fundamental record contains a Title_Category record.
The Title_Category record contains a Title record and a Category record.
All records contain an ID field and one or more data fields (such as text).

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • @philipxy: I was thinking that there may be many ingredients that use a common Title and Category, which is why I placed them into a separate table. I didn't want to duplicate the pair. – Thomas Matthews Aug 09 '17 at 15:39
  • @philipxy: I use the term "nested" because I couldn't think of the proper term. It's not direct containment. And not direct foreign table reference. – Thomas Matthews Aug 09 '17 at 15:41
  • When I asked whether you need ID_Title_Category, I asked as part of wondering whether to suggest that you read an intro to information modeling & relational databases. (Your question, if I understand it, is basic.) I meant that if (ID_Title, ID_Category) pairs are unique & not null then that pair can be PK & elsewhere FK and you don't need ID_Title_Category. Although there are reasons why people add ids in such cases anyway. – philipxy Aug 09 '17 at 17:00
  • What is some *English* syntax giving the vague "based on the fields" in detail? – philipxy Aug 10 '17 at 20:59
  • @philipxy: See my **Edit1**. I'm investigating dropping the "Title_Category" table in favor of a compound key. – Thomas Matthews Aug 10 '17 at 21:19
  • Re my "*English* syntax" request: My answer *already* has examples. But I commented to emphasize that if you actually try to make an English statement of *what rows are in your query result per either the situation or the base table values or both* then *that* you can translate into SQL. "looking up values" & "based on" describe/reference/summarize but don't *specify* that. Neither does your edit--it actually doesn't even say what goes in the base *or* query result tables. Force yourself to describe what rows the result holds, in terms of base tables or base table meanings/predicates or both. – philipxy Aug 10 '17 at 22:13

1 Answers1

0

I want to select the ID_Title_Category field where Titles.Title = "Hamburger" and Categories.Category = "Meat".

That doesn't make sense. Presumably you mean something like you want select ID_Title_Category from Title_Category wherecondition. But what is condition? What are rows Titles and Categories? You don't need to know more SQL to say that.

You might mean that you want select ID_Title_Category from Title_Category rows where row (ID_Title) is in select ID_Table from Titles where Title = 'Hamburger' and where row (ID_Category) is in select ID_Category from Categories where Category = 'Meat'.

Then it is helpful to know that SQL lets you write (...) in (subselect).

select ID_Title_Category
from Title_Category
where (ID_Title) in (select ID_Title from Titles where Title = 'Hamburger')
and (ID_Category) in (select ID_Category from Categories where Category = 'Meat')

Or you might mean that you want select ID_Title_Category from Title_Category rows TC (say) where there exist values for T.ID_Title & C.ID_Category where row T (say) is in Titles and TC.ID_Title = T.ID_Title and T.Title = 'Hamburger' and row C (say) is in Categories and TC.ID_Category = C.ID_Category and C.Category = 'Meat'.

Then it is good to know that in SQL T cross join U is rows (T.X,...,U.Y,...) where row (T.X,...) is in T and row (U.Y,...) is in U. (, is cross join binding looser than the various joins.)

select TC.ID_Title_Category
from Title_Category TC
cross join Titles T
cross join Categories C
where TC.ID_Title = T.ID_Title and T.Title = 'Hamburger'
and TC.ID_Category = C.ID_Category and C.Category = 'Meat'

Also, T cross join U and condition can be expressed as T join U oncondition.

select TC.ID_Title_Category
from Title_Category TC
join Titles T
on TC.ID_Title = T.ID_Title and T.Title = 'Hamburger'
join Categories C
on TC.ID_Category = C.ID_Category and C.Category = 'Meat'

You could write another version knowing that in SQL there exists a row in subselect when EXISTS(subselect).

We don't need to know constraints (PK, UNIQUE, FK, etc) to query. We do need to what each base table row says about the situation. Then we can express what rows are in the result via what rows are in base tables. To use relation operators we need to know how to translate between predicate expressions & relation expressions. We can also describe the rows in the result via what each result row says about the situation. (Which is how you would justify intuitive use of in.) Is there any rule of thumb to construct SQL query from a human-readable description?

philipxy
  • 14,867
  • 6
  • 39
  • 83