具有双重嵌套级别的 SQL 查询

Posted

技术标签:

【中文标题】具有双重嵌套级别的 SQL 查询【英文标题】:SQL Query with double nested level 【发布时间】:2014-11-02 21:31:58 【问题描述】:

我正在学习斯坦福的免费在线课程(我推荐!),但我遇到了以下问题。请帮忙。

找出所有与加布里埃尔成为朋友的学生的姓名。

这是我能想到的最好的。

select name 
from highschooler h 
where h.id exists in (
    select friend.id1 
    from friend 
    where friend.id2 exists in (
        select h.id 
        from highschooler h2 
        where h2.name="gabriel"
    )
);

尽管我使用 mysql 工作台作为测试场所,但我需要在 SQL Lite 中运行查询(我知道它们对于像这样的基本查询相对相似)。

/* Create the schema for our tables */
create table Highschooler(ID int, name text, grade int);
create table Friend(ID1 int, ID2 int);
create table Likes(ID1 int, ID2 int);

/* Populate the tables with our data */
insert into Highschooler values (1510, 'Jordan', 9);
insert into Highschooler values (1689, 'Gabriel', 9);
insert into Highschooler values (1381, 'Tiffany', 9);
insert into Highschooler values (1709, 'Cassandra', 9);
insert into Highschooler values (1101, 'Haley', 10);
insert into Highschooler values (1782, 'Andrew', 10);
insert into Highschooler values (1468, 'Kris', 10);
insert into Highschooler values (1641, 'Brittany', 10);
insert into Highschooler values (1247, 'Alexis', 11);
insert into Highschooler values (1316, 'Austin', 11);
insert into Highschooler values (1911, 'Gabriel', 11);
insert into Highschooler values (1501, 'Jessica', 11);
insert into Highschooler values (1304, 'Jordan', 12);
insert into Highschooler values (1025, 'John', 12);
insert into Highschooler values (1934, 'Kyle', 12);
insert into Highschooler values (1661, 'Logan', 12);

insert into Friend values (1510, 1381);
insert into Friend values (1510, 1689);
insert into Friend values (1689, 1709);
insert into Friend values (1381, 1247);
insert into Friend values (1709, 1247);
insert into Friend values (1689, 1782);
insert into Friend values (1782, 1468);
insert into Friend values (1782, 1316);
insert into Friend values (1782, 1304);
insert into Friend values (1468, 1101);
insert into Friend values (1468, 1641);
insert into Friend values (1101, 1641);
insert into Friend values (1247, 1911);
insert into Friend values (1247, 1501);
insert into Friend values (1911, 1501);
insert into Friend values (1501, 1934);
insert into Friend values (1316, 1934);
insert into Friend values (1934, 1304);
insert into Friend values (1304, 1661);
insert into Friend values (1661, 1025);
insert into Friend select ID2, ID1 from Friend;

insert into Likes values(1689, 1709);
insert into Likes values(1709, 1689);
insert into Likes values(1782, 1709);
insert into Likes values(1911, 1247);
insert into Likes values(1247, 1468);
insert into Likes values(1641, 1468);
insert into Likes values(1316, 1304);
insert into Likes values(1501, 1934);
insert into Likes values(1934, 1501);
insert into Likes values(1025, 1101);

非常感谢任何帮助!

【问题讨论】:

【参考方案1】:

为此,您需要两次引用 Highschooler 表,基本上建立关系 Highschooler -> Friend -> Highschooler

这是怎么做的:

select h1.name
from Highschooler h1
inner join Friend f on f.ID1 = h1.ID
inner join Highschooler h2 on f.ID2 = h2.ID
where h2.name = 'Gabriel'

这是带有上述查询的SQL Fiddle。

【讨论】:

@Andrey 我认为我们不想在这里与众不同。表格中可以有多个名称。【参考方案2】:

我建议你做的是把它分解成小块,然后把它们重新组合在一起。

首先,让我们获取所有名为 gabriel 的人的 ID:

SELECT s.id
FROM highschooler s
WHERE s.name = 'Gabriel';

现在,我们可以找到该 id 作为 id1 存在的所有好友列表:

SELECT f.id2
FROM friend f
WHERE f.id1 IN(SELECT s.id
                FROM highschooler s
                WHERE s.name = 'Gabriel');

由于您已将表格设置为包括列出相同两个朋友的两种方式,因此您无需担心会做相反的事情(其中 f.id2 是 Gabriel)。

现在,您可以将上述查询与 highschooler 表连接起来以获取他们的名字。

SELECT s.name
FROM highschooler s
JOIN(SELECT f.id2
    FROM friend f
    WHERE f.id1 IN(SELECT s.id
                    FROM highschooler s
                    WHERE s.name = 'Gabriel')
     ) t
ON t.id2 = s.id;

这是一个SQL Fiddle 的示例。

【讨论】:

以上是关于具有双重嵌套级别的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

从嵌套字典结构列表(具有两个级别)创建数据框的 Pythonic 方法是啥?

使用 Itertools 具有内部中断的可变级别的嵌套循环

Oracle 是不是关联嵌套在任何级别的子查询?

嵌套查询到未知级别 GraphQL [重复]

具有 3 个级别的 MongoDB 嵌套查找

Laravel 附加具有相关关系的属性将导致达到最大函数嵌套级别