从孩子 - 祖父母关系中的不同表中获取姓名

时间:2013-01-07 23:34:01

标签: mysql parent-child

我有三张桌子:

CREATE TABLE category (id integer, parent_id integer);
CREATE TABLE category_name (id integer, name (varchar(20), language_id);
CREATE TABLE language (language_id integer, language_name);

我可以通过以下语句获得子父母与祖父母的关系:

SELECT c.id, c.parent_id, p.parent_id 
FROM category AS p, category AS c 
WHERE p.id = c.parent_id AND p.parent_id IS NOT NULL;

但是我需要从表category_name中获取孩子,父母和祖父母的名字,其中language_id = 3

获取名称的查询没有子父母祖父母关系将是这样的:

SELECT c.id, n.name
FROM category c
LEFT JOIN category_name n ON c.id = n.id AND language_ID = 3

但是如何将两个语句合并为一个,以便我实际上得到三个名称列? 也就是说,每一行都应该有自己的ID和名称,它的父级和祖父母(如果后者存在)

如何进行此合并查询?

以下是表格和一些示例数据:

CREATE TABLE category (id integer, parent_id integer);
INSERT INTO category VALUES (1,null);
INSERT INTO category VALUES (2,null);
INSERT INTO category VALUES (3,1);
INSERT INTO category VALUES (4,2);
INSERT INTO category VALUES (5,2);
INSERT INTO category VALUES (6,4);
INSERT INTO category VALUES (7,2);
INSERT INTO category VALUES (8,7);
INSERT INTO category VALUES (9,7);
INSERT INTO category VALUES (10,7);
INSERT INTO category VALUES (11,3);

CREATE TABLE category_name (id integer, name varchar(20), language_id integer);
INSERT INTO category_name VALUES (1, 'CDs', 3);
INSERT INTO category_name VALUES (2, 'Books', 3);
INSERT INTO category_name VALUES (3, 'Music', 3);
INSERT INTO category_name VALUES (4, 'Novels', 3);
INSERT INTO category_name VALUES (5, 'Childrens books', 3);
INSERT INTO category_name VALUES (6, 'European', 3);
INSERT INTO category_name VALUES (7, 'Science', 3);
INSERT INTO category_name VALUES (8, 'Math', 3);
INSERT INTO category_name VALUES (9, 'Informatics', 3);
INSERT INTO category_name VALUES (10, 'Physics', 3);
INSERT INTO category_name VALUES (11, 'Classic', 3);
INSERT INTO category_name VALUES (1, 'CDs', 4);
INSERT INTO category_name VALUES (2, 'Livres', 4);
INSERT INTO category_name VALUES (3, 'Musique', 4);
INSERT INTO category_name VALUES (4, 'Romans', 4);

CREATE TABLE language (language_id integer, language_name varchar(15));
INSERT INTO language (3, 'English');
INSERT INTO language (4, 'French');

以下是我想了解一些样本(对于c.id = 5和8):

c.id | c.parent_id | p.parent_id | nameChild          | nameParent | nameGrandparent
5    | 2           | null        | 'Children's books' | 'Books'    | null
8    | 7           | 2           | 'Math'             | 'Science'  | 'Books'

我已尝试过以下代码,但它给出了 错误代码:1054。'on clause'

中的未知列'p.parent_id'
SELECT c.id, c.parent_id, p.parent_id, nc.name, np.name, ng.name 
FROM category1 AS p, category1 AS c 
LEFT JOIN category_name1 AS nc ON c.id = nc.id AND nc.language_id = 3
LEFT JOIN category_name1 AS np ON c.parent_id = np.id AND np.language_id = 3
LEFT JOIN category_name1 AS ng ON p.parent_id = ng.id AND ng.language_id = 3 AND p.parent_id IS NOT NULL
WHERE p.id = c.parent_id AND p.parent_id IS NOT NULL;

我找出孩子和父母的名字没有问题,但祖父母的名字似乎不在我的掌握之中:(

以下是代码正常工作!

SELECT x.id, x.pid, x.gpid, 
nc.name childName, np.name parentName, ng.name gpName 
FROM 
(SELECT  c.id , c.parent_id AS pid, p.parent_id AS gpid
FROM
category AS c
LEFT JOIN category AS p ON p.id = c.parent_id
) x


LEFT JOIN category_name AS nc ON x.id = nc.id AND nc.language_id = 3
LEFT JOIN category_name AS np ON x.pid = np.id AND np.language_id = 3
LEFT JOIN category_name AS ng ON x.gpid = ng.id AND ng.language_id = 3;

2 个答案:

答案 0 :(得分:1)

请试一试并发表评论。查询和结果都基于我自己的样本。

此查询选择带有language name内容的category namelanguage id =,按parent id分组。

查询:

select l.language_name, cl.name, c.parent_id
from category c
left join 
category_name cl
on c.parent_id = cl.id
inner join 
language l
on cl.language_id = l.language_id
where l.language_id = 30
group by c.parent_id
;

结果:

LANGUAGE_NAME   NAME    PARENT_ID
eng             cat4c   4

以下查询为每个category name选择parent idlanguage

查询:

select l.language_name, cl.name, c.parent_id
from language l
left join 
category_name cl
on cl.language_id = l.language_id
left join 
category c
on c.parent_id = cl.id
group by l.language_id
;

结果:

LANGUAGE_NAME   NAME    PARENT_ID
jpn             cat1    (null)
kor             cat3    3
eng             cat4    4

使用示例数据编辑每个OP的更新问题&预期结果

查询:

select x.id, x.pid, x.gpid, 
cl.name ccat, cl2.name pcat, cl3.name gpcat
from
(SELECT c.id , c.parent_id as pid, 
p.parent_id gpid
FROM category AS c
left join category AS p 
on p.id = c.parent_id 
WHERE c.id in (5, 8)
) x
left join 
category_name cl
on cl.id = x.id
left join category_name cl2
on cl2.id = x.pid
left join category_name cl3
on cl3.id = x.gpid
group by x.id
;

结果:

ID  PID     GPID    CCAT        PCAT    GPCAT
5   2       (null)  Children    Books   (null)
8   7       2       Math        Science Books

答案 1 :(得分:0)

这样的事情应该有效:

SELECT 
c.id AS childId, cname.name AS childName,
p.id AS parentId, pname.name AS parentName,
g.id AS grandparentId, gname.name AS grandparentName
FROM category p
INNER JOIN category c ON (p.id = c.parent_id)
LEFT JOIN category g ON (p.parent_id = g.id)
LEFT JOIN category_name cname ON (c.id = cname.id AND cname.language_ID = 3)
LEFT JOIN category_name pname ON (p.id = pname.id AND pname.language_ID = 3)
LEFT JOIN category_name gname ON (g.id = gname.id AND gname.language_ID = 3)
WHERE p.parent_id IS NOT NULL;

我觉得应该有一个更简洁的方法来做到这一点,但目前看不到它。