SQLite 中的子选择
Sub-selects in SQLite
问题
我最近要完成一项技术测试,这需要我执行一个相当复杂的 SQL 查询,我想先了解一下我可能收到的反馈,我给出的答案是否正确,以及如何改进。
这是我对问题的释义:
Suppose we have a website selling hats, for which we want to build a database. Each type of hat has a size, price, etc. Each type of hat can also fall into none, one or more categories, and these categories can themselves be public or private.
Do the following:
- Write pseudo-SQL code creating the tables necessary to model the above.
- Write a query which will return the records for types of hats which belong to at least 5 public categories.
我的尝试
由于我的大部分经验都是使用 SQLite,所以我从 SQLite 的角度解决了这个问题,我在回答的评论中写了这个。
关于上面的第(1)点,我创建了三个table:Hat
、Category
和BelongsToCategory
,最后一个是连接table 对于前两个。我制作了 public
Category
table 的一列,类型为 INTEGER
:0 表示假,1 表示真。
关于第(2)点,这是我的查询:
SELECT *
FROM Hat
WHERE
(SELECT COUNT(*)
FROM BelongsToCategory
JOIN Category ON Category.code = BelongsToCategory.category
WHERE (BelongsToCategory.hat = Hat.code) AND (Category.public = 1))
>= 5
测试我的尝试
我以下列方式测试了我的尝试:
- 我制作了自己的 .db 文件。
- 我使用 数据库浏览器为 SQLite 打开了上述文件。
- 我创建了我的 tables,如上所述。
- 我给那些table添加了数据,如下:
- 我在
Hat
table 中添加了三个新记录:hat1、hat2 和 hat3。
- 我在
Category
table 中添加了六个新记录:cat1 到 cat6,其中 cat1 到 cat5 是 public,而 cat6 是私有的。
- 我在
BelongsToCategory
table中添加了记录,这样hat1属于类别cat1到cat5,hat2只属于类别1,hat3属于类别cat1到cat4,也属于cat6。
- 我运行上面的SQL代码。
当我运行上面的SQL代码时,它返回了hat1的记录。任务完成!没那么快……当我试着玩弄一下,将 5 更改为 4、或 3、2 等时,我不断获得 hat1 的记录,除此之外别无他法。到1的时候才开始弹出hat3,一直没看到hat2。
这是怎么回事? 我的查询有问题吗? 或者这是 SQLite 浏览器中的错误?
我想知道的
- 以上SQL查询是否正确?
- 如何改进?
我认为您的查询没有任何问题(我已经对其进行了测试并且它按预期工作)。因此,我相信您可能没有按预期插入数据。
如果您将计数子查询作为附加列添加到主查询并使用 >= 0,您可以看到计数并了解发生了什么计数
例如:-
SELECT *, (SELECT COUNT(*)
FROM BelongsToCategory
JOIN Category ON Category.code = BelongsToCategory.category
WHERE (BelongsToCategory.hat = Hat.code) AND (Category.public = true)) AS cat_count
FROM Hat
WHERE
(SELECT COUNT(*)
FROM BelongsToCategory
JOIN Category ON Category.code = BelongsToCategory.category
WHERE (BelongsToCategory.hat = Hat.code) AND (Category.public = true))
>= 0
;
下面是用来测试上面的:-
PRAGMA foreign_keys = ON;
DROP TABLE IF EXISTS BelongsToCategory;
DROP TABLE IF EXISTS Hat;
DROP TABLE IF EXISTS Category;
CREATE TABLE IF NOT EXISTS Hat (code INTEGER PRIMARY KEY, hattype TEXT, hatprice REAL, hatsize REAL, hatetc TEXT);
CREATE TABLE IF NOT EXISTS Category (code INTEGER PRIMARY KEY, category TEXT, public INTEGER);
CREATE TABLE IF NOT EXISTS BelongsToCategory (
hat INTEGER REFERENCES Hat(code) ON DELETE CASCADE ON UPDATE CASCADE
, category INTEGER REFERENCES Category(code) ON DELETE CASCADE ON UPDATE CASCADE
, PRIMARY KEY(hat,category)
)
;
INSERT INTO Category VALUES(1,'cat1',true),(2,'cat2',true),(3,'cat3',true),(4,'cat4',true),(5,'cat5',true),(6,'cat6',false);
INSERT INTO Hat VALUES(1,'hat1',100,7,'other'),(2,'hat2',90,6,'other'),(3,'hat3',95,5,'other'),(4,'hat4',110,8,'other'),(5,'hat5',120,8,'other');
INSERT INTO BelongsToCategory VALUES
(1,1),(1,2),(1,3),(1,4),(1,5),(1,6)
,(2,1)
,(3,1),(3,2),(3,3),(3,4)
,(5,6),(5,1)
;
SELECT *, (SELECT COUNT(*)
FROM BelongsToCategory
JOIN Category ON Category.code = BelongsToCategory.category
WHERE (BelongsToCategory.hat = Hat.code) AND (Category.public = true)) AS cat_count
FROM Hat
WHERE
(SELECT COUNT(*)
FROM BelongsToCategory
JOIN Category ON Category.code = BelongsToCategory.category
WHERE (BelongsToCategory.hat = Hat.code) AND (Category.public = true))
>= 0
;
上面的结果(使用>=0):-
(使用>=5):-
(使用>=4):-
问题
我最近要完成一项技术测试,这需要我执行一个相当复杂的 SQL 查询,我想先了解一下我可能收到的反馈,我给出的答案是否正确,以及如何改进。
这是我对问题的释义:
Suppose we have a website selling hats, for which we want to build a database. Each type of hat has a size, price, etc. Each type of hat can also fall into none, one or more categories, and these categories can themselves be public or private.
Do the following:
- Write pseudo-SQL code creating the tables necessary to model the above.
- Write a query which will return the records for types of hats which belong to at least 5 public categories.
我的尝试
由于我的大部分经验都是使用 SQLite,所以我从 SQLite 的角度解决了这个问题,我在回答的评论中写了这个。
关于上面的第(1)点,我创建了三个table:Hat
、Category
和BelongsToCategory
,最后一个是连接table 对于前两个。我制作了 public
Category
table 的一列,类型为 INTEGER
:0 表示假,1 表示真。
关于第(2)点,这是我的查询:
SELECT *
FROM Hat
WHERE
(SELECT COUNT(*)
FROM BelongsToCategory
JOIN Category ON Category.code = BelongsToCategory.category
WHERE (BelongsToCategory.hat = Hat.code) AND (Category.public = 1))
>= 5
测试我的尝试
我以下列方式测试了我的尝试:
- 我制作了自己的 .db 文件。
- 我使用 数据库浏览器为 SQLite 打开了上述文件。
- 我创建了我的 tables,如上所述。
- 我给那些table添加了数据,如下:
- 我在
Hat
table 中添加了三个新记录:hat1、hat2 和 hat3。 - 我在
Category
table 中添加了六个新记录:cat1 到 cat6,其中 cat1 到 cat5 是 public,而 cat6 是私有的。 - 我在
BelongsToCategory
table中添加了记录,这样hat1属于类别cat1到cat5,hat2只属于类别1,hat3属于类别cat1到cat4,也属于cat6。
- 我在
- 我运行上面的SQL代码。
当我运行上面的SQL代码时,它返回了hat1的记录。任务完成!没那么快……当我试着玩弄一下,将 5 更改为 4、或 3、2 等时,我不断获得 hat1 的记录,除此之外别无他法。到1的时候才开始弹出hat3,一直没看到hat2。
这是怎么回事? 我的查询有问题吗? 或者这是 SQLite 浏览器中的错误?
我想知道的
- 以上SQL查询是否正确?
- 如何改进?
我认为您的查询没有任何问题(我已经对其进行了测试并且它按预期工作)。因此,我相信您可能没有按预期插入数据。
如果您将计数子查询作为附加列添加到主查询并使用 >= 0,您可以看到计数并了解发生了什么计数
例如:-
SELECT *, (SELECT COUNT(*)
FROM BelongsToCategory
JOIN Category ON Category.code = BelongsToCategory.category
WHERE (BelongsToCategory.hat = Hat.code) AND (Category.public = true)) AS cat_count
FROM Hat
WHERE
(SELECT COUNT(*)
FROM BelongsToCategory
JOIN Category ON Category.code = BelongsToCategory.category
WHERE (BelongsToCategory.hat = Hat.code) AND (Category.public = true))
>= 0
;
下面是用来测试上面的:-
PRAGMA foreign_keys = ON;
DROP TABLE IF EXISTS BelongsToCategory;
DROP TABLE IF EXISTS Hat;
DROP TABLE IF EXISTS Category;
CREATE TABLE IF NOT EXISTS Hat (code INTEGER PRIMARY KEY, hattype TEXT, hatprice REAL, hatsize REAL, hatetc TEXT);
CREATE TABLE IF NOT EXISTS Category (code INTEGER PRIMARY KEY, category TEXT, public INTEGER);
CREATE TABLE IF NOT EXISTS BelongsToCategory (
hat INTEGER REFERENCES Hat(code) ON DELETE CASCADE ON UPDATE CASCADE
, category INTEGER REFERENCES Category(code) ON DELETE CASCADE ON UPDATE CASCADE
, PRIMARY KEY(hat,category)
)
;
INSERT INTO Category VALUES(1,'cat1',true),(2,'cat2',true),(3,'cat3',true),(4,'cat4',true),(5,'cat5',true),(6,'cat6',false);
INSERT INTO Hat VALUES(1,'hat1',100,7,'other'),(2,'hat2',90,6,'other'),(3,'hat3',95,5,'other'),(4,'hat4',110,8,'other'),(5,'hat5',120,8,'other');
INSERT INTO BelongsToCategory VALUES
(1,1),(1,2),(1,3),(1,4),(1,5),(1,6)
,(2,1)
,(3,1),(3,2),(3,3),(3,4)
,(5,6),(5,1)
;
SELECT *, (SELECT COUNT(*)
FROM BelongsToCategory
JOIN Category ON Category.code = BelongsToCategory.category
WHERE (BelongsToCategory.hat = Hat.code) AND (Category.public = true)) AS cat_count
FROM Hat
WHERE
(SELECT COUNT(*)
FROM BelongsToCategory
JOIN Category ON Category.code = BelongsToCategory.category
WHERE (BelongsToCategory.hat = Hat.code) AND (Category.public = true))
>= 0
;
上面的结果(使用>=0):-
(使用>=5):-
(使用>=4):-