到目前为止,我可以使用以下MySQL查询:
SELECT CONCAT('program:', program_pk) AS global_id,
program_name AS name,
NULL AS parent_global_id
FROM program
UNION ALL
SELECT CONCAT('theme:', theme_pk) AS global_id,
theme_name AS name,
CONCAT('program:', program_pk) AS parent_global_id
FROM theme CROSS JOIN program
UNION ALL
SELECT DISTINCT
CONCAT('theme:', theme_fk, ',strand:', strand_name) AS global_id,
strand_name AS name,
CONCAT('theme:', theme_fk) AS parent_global_id
FROM strand
UNION ALL
SELECT CONCAT('strand_year:', strand_pk) AS global_id,
strand.year AS name,
CONCAT('theme:', theme_fk, ',strand:', strand_name) AS parent_global_id
FROM strand
UNION ALL
SELECT CONCAT('strand_year:', strand_pk, ',unit:', unit_pk) AS global_id,
CONCAT(unit.unit_code, ' ', unit.unit_name) AS name,
CONCAT('strand_year:', strand_pk) AS parent_global_id
FROM strand LEFT JOIN unit ON strand.year = unit.year
表格程序
+------------+--------------+
| program_pk | program_name |
+------------+--------------+
表格主题
+----------+------------+
| theme_pk | theme_name |
+----------+------------+
表链
+-----------+-------------+----------+------+
| strand_pk | strand_name | theme_fk | year |
+-----------+-------------+----------+------+
表格单位
+---------+-----------+-----------+--------+------+----------+
| unit_pk | unit_code | unit_name | points | year | theme_fk |
+---------+-----------+-----------+--------+------+----------+
关系是:
程序->主题->链->年->单位
我现在需要向表中添加表learning_event
表learning_event
+-------------------+---------------------+---------+-----------+----------------+
| learning_event_pk | learning_event_name | unit_fk | strand_fk | core_condition |
+-------------------+---------------------+---------+-----------+----------------+
将来自父unit
的学习事件分支给:
程序->主题->链->年->单位->学习活动
请注意,对于给定的链和单位,仅应显示与链相关的学习事件。
我已经玩过这个游戏了,但是真的不确定如何将它与学习活动与单元和链相关联。
更新
在JSON格式下,现有查询的内容如下:
{
"name": "MD",
"children": [{
"name": "Professional",
"children": [{
"name": "Professional Behavours",
"children": [{
"name": "Year 1",
"children": [{
"name": "IMED4443 Integrated Medical Sciences 1"
}, {
"name": "IMED4444 Integrated Medical Sciences 2"
}]
}
我正在寻找的新输出如下:
"name": "MD",
"children": [{
"name": "Professional",
"children": [{
"name": "Professional Behavours",
"children": [{
"name": "Year 1",
"children": [{
"name": "IMED4443 Integrated Medical Sciences 1"
}, {
"name": "IMED4444 Integrated Medical Sciences 2",
"children": [{
"name": "Lecture - CVS"
}, {
"name": "Lecture - Type 1 Diabetes"
}...
并且学习事件仅应显示与单位和链的关系。
仅供参考,使用以下方式处理关系:
$result = $connection->query($query);
$data = array();
while ($row = $result->fetch_object()) {
$data[$row->global_id] = $row;
}
$roots = array();
foreach ($data as $row) {
if ($row->parent_global_id === null) {
$roots[]= $row;
} else {
$data[$row->parent_global_id]->children[] = $row;
}
unset($row->parent_global_id);
unset($row->global_id);
}
$json = json_encode($roots);
新更新
该查询由Jonathan Willcock提供并由我修改,它很接近,它显示了所有主题和子线的年,以及第一个主题“ Professional”的单元和学习事件,但未显示单位其他主题。
SELECT CONCAT('program:', program_pk) AS global_id,
program_name AS name,
NULL AS parent_global_id
FROM program
UNION ALL
SELECT CONCAT('theme:', theme_pk) AS global_id,
theme_name AS name,
CONCAT('program:', program_fk) AS parent_global_id
FROM theme
UNION ALL
SELECT
CONCAT('theme:', theme_fk, ',strand:', strand_name) AS global_id,
strand_name AS name,
CONCAT('theme:', theme_fk) AS parent_global_id
FROM strand
UNION ALL
SELECT
CONCAT('theme:', theme_fk, ',strand:', strand_name, ',strandyear:', strandyear_name) AS global_id,
strandyear_name AS name,
CONCAT('theme:', theme_fk, ',strand:', strand_name) AS parent_global_id
FROM strandyear sy
INNER JOIN strand s ON s.strand_pk = sy.strand_fk
UNION ALL
SELECT
CONCAT('theme:', theme_fk, ',strand:', strand_name, ',strandyear:', strandyear_name, ',unit:', unit_name) AS global_id,
unit_name AS name,
CONCAT('theme:', theme_fk, ',strand:', strand_name, ',strandyear:', strandyear_name) AS parent_global_id
FROM unit u
INNER JOIN strandyear sy ON u.strandyear_fk = sy.strandyear_pk
INNER JOIN strand s ON s.strand_pk = sy.strand_fk
UNION ALL
SELECT
CONCAT('theme:', theme_fk, ',strand:', strand_name, ',strandyear:', strandyear_name, ',unit:', unit_name, ',learning_event:', learning_event_name) AS global_id,
learning_event_name AS name,
CONCAT('theme:', theme_fk, ',strand:', strand_name, ',strandyear:', strandyear_name, ',unit:', unit_name) AS parent_global_id
FROM learning_event le
INNER JOIN unit u ON u.unit_pk = le.unit_fk
INNER JOIN strandyear sy ON u.strandyear_fk = sy.strandyear_pk
INNER JOIN strand s ON s.strand_pk = sy.strand_fk
请注意,parent_global_id必须与前面的global_id相同。
最后更新
上面的查询工作正常!问题是单位表。更新db-fiddle
答案 0 :(得分:1)
如果所需的层次结构是程序->主题->链->年->单位-> learning_event,则应调整表结构以反映此情况。特别是主题应该在主题和程序之间具有外键关系,并且您需要一年的额外级别。在主题和程序之间使用外键避免了交叉连接的需要。交叉连接有一种咬你的习惯,通常应避免。
如果您查看此db fiddle,将会发现我已经进行了这些更改。我曾称年级为stryearyear以避免使用保留字,但其意图应明确。现在,联接变为内部联接(而不是左联接),以从树中的更高级别中获取描述值,并且最低级别(learning_events)自动仅包含与strand,year和unit匹配的值,除了其他原因外通过简单的权宜之计,即每个级别在上一层都有一个外键,结构本身就可以保证它。
请注意,外键有效地链接了链接。例如,您不需要在learning_event和strand之间使用特定的外键,因为链中的中间键可以保证这种关系。
答案 1 :(得分:0)
假设program -> theme -> strand -> year -> unit -> learning event
表示
program
具有1个或多个themes
theme
有1个或更多strands
等等那么你需要
CREATE TABLE program (program_id ...)
CREATE TABLE theme (theme_id ..., program_id, ...)
CREATE TABLE strand (strand_id ..., theme_id, ...)
etc
这在每对连续的一对表之间实现了1:1:1的关系。
一个典型的例子会更详细:
CREATE TABLE theme (
theme_id INT UNSIGNED AUTO_INCREMENT NOT NULL,
theme_name VARCHAR(99) NOT NULL,
program_id INT UNSIGNED NOT NULL, -- link to the program this theme is in
PRIMARY KEY(theme_id)
) ENGINE=InnoDB
((您可以选择添加FOREIGN KEY
约束,以进一步强调我包含的评论。)