Sqlite левое соединение составных ключей - PullRequest
0 голосов
/ 09 мая 2018

При развертывании сводного запроса SQLite для статического ORM проблема заключается в том, что для пропущенных значений требуются значения NULL.

table student
student_id | name
    1       "Fred"
    2       "Tim"
PK(`student_id`)

table grade 
student_id | data_id | grade
    1           1       5.0
    1           2       5.0
    2           2       5.0
PK(`student_id`,`data_id`),
FK(student.studentid)
FK(data.data_id)

table data 
data_id | description
   1       "summer"
   2       "autumn"
PK(`data_id`)

Мне нужно, чтобы результаты включали пустую строку для статической ORM для правильной табулирования. На мой взгляд, это должно означать ЛЕВОЕ присоединение:

SELECT * FROM student
join grade using (student_id)
LEFT OUTER JOIN data
ON grade.data_id = data.data_id

Поскольку Тим отсутствовал на летнем экзамене, нет строки для student_id | data_id PK_pair (2,1) в классе таблицы.

Запрос в настоящее время возвращает:

sID |  name  | dID | grade | description
"1"   "Fred"   "1"   "5.0"   "summer"
"1"   "Fred"   "2"   "5.0"   "autumn"
"2"   "Tim"    "2"   "5.0"   "autumn"

Эта строка отсутствует в результате:

sID |  name  | dID | grade | description
"2"    "Tim"   "1"    null    "summer"

1 Ответ

0 голосов
/ 09 мая 2018

Левое соединение возвращает строки внутреннего соединения плюс несопоставленные строки левой таблицы, расширенные нулями. Если вы считаете, что хотите левое соединение, вам нужно определить связанное внутреннее соединение. Здесь вы, кажется, не знаете таблицы и условия. Но вы, кажется, по крайней мере хотите строки для каждой возможной пары студент-данные; действительно, для каждой комбинации (student_id, name) & (data_id, description). Так что те должны быть в левой таблице. Кроме того, оценка столбца равна нулю, поэтому, вероятно, она связана с правильной таблицей. Может быть, вы хотите:

select *
from students
natural join data
left natural join grade

Я выбрал этот запрос, потому что он (без нулей в общих столбцах и без повторяющихся строк):

/* rows where
    student [student_id] has name [name]
and term [data_id] has description [description]
and (student [student_id] got grade [grade] in term [data_id]
    or not exists grade [student [student_id] got grade [grade] in term [data_id]]
    and [grade] is null
    )
/*

Sqlite левое соединение составных клавиш

Хотя ограничения говорят нам кое-что о результате запроса, они не нужны для запроса. Требуется критерий членства результата запроса, то есть его предикат (характеристика) . Который в данном случае я дал в этом коде комментарий. Обратите внимание, как он построен из критериев / предикатов базовых таблиц:

  • natural join содержит строки, удовлетворяющие and критериев / предикатов его таблиц.
  • left natural join содержит строки, удовлетворяющие and критерия членства его левой таблицы с определенным or с использованием критерия / предиката правой таблицы и условия, что каждый столбец уникален для правой таблицы is null.

Есть ли эмпирическое правило для построения запроса SQL из понятного человеку описания? .

(Если столбцы description & name имеют одно и то же имя, вам придется либо переименовать его перед natural join, либо использовать inner join using (student_id, data_id). Но, опять же, это может возникнуть из-за составления соответствующего сказуемое.)

...