0

为静态 ORM 展开 SQLite 数据透视查询,问题是它需要空值来表示缺失值。

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

由于 Tim 暑期考试缺席,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"
4

1 回答 1

2

左连接返回内连接行加上由空值扩展的不匹配的左表行。如果你认为你想要一个左连接,那么你需要识别相关的内连接。在这里,您似乎不知道表格和条件。但是您似乎至少希望每个可能的学生数据对都有一行;实际上,对于 (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)。但同样,这将来自于组成适当的谓词。)

于 2018-05-09T08:38:02.713 回答