简体   繁体   English

SQLite 中的子选择

[英]Sub-selects in SQLite

The Problem问题

I was recently completing a technical test, which required me to carry out a rather convoluted SQL query , and I'd like to know, ahead of any feedback I might receive, whether the answer I gave was correct, and how it might be improved.我最近正在完成一项技术测试,这需要我执行一个相当复杂的SQL 查询,我想在收到任何反馈之前知道我给出的答案是否正确,以及如何改进.

Here's my paraphrase of the problem:这是我对问题的解释

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:请执行下列操作:

  1. Write pseudo-SQL code creating the tables necessary to model the above.编写伪 SQL 代码,创建上述 model 所需的表。
  2. Write a query which will return the records for types of hats which belong to at least 5 public categories .编写一个查询,该查询将返回属于至少 5 个公共类别的帽子类型的记录。

My Attempt我的尝试

Since the bulk of my experience is with SQLite, I tackled this from an SQLite point of view, and I wrote this in a comment in my answer.由于我的大部分经验是 SQLite,我从 SQLite 的角度解决了这个问题,我在我的回答中的评论中写了这个。

Regarding point (1) above, I created three tables: Hat , Category and BelongsToCategory , with the last being a join table for the first two.关于上面的第 (1) 点,我创建了三个表: HatCategoryBelongsToCategory ,最后一个是前两个的连接表。 I made public a column of the Category table, of INTEGER type: 0 for false, 1 for true.publicCategory表的一列, INTEGER类型:0 为假,1 为真。

As for point (2), this is my query:至于第(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

Testing My Attempt测试我的尝试

I tested my attempt in the following fashion:我以以下方式测试了我的尝试:

  • I made my own.db file.我制作了自己的.db 文件。
  • I opened said file using the Database Browser for SQLite .我使用SQLite 的数据库浏览器打开了该文件。
  • I created my tables, as above.如上所述,我创建了我的表。
  • I added data to those tables, as follows:我将数据添加到这些表中,如下所示:
    • I added three new records to the Hat table: hat1, hat2 and hat3.我在Hat表中添加了三个新记录:hat1、hat2 和 hat3。
    • I added six new records to the Category table: cat1 to cat6, where cat1 to cat5 were public, and cat6 was private.我在Category表中添加了 6 条新记录:cat1 到 cat6,其中 cat1 到 cat5 是公共的,而 cat6 是私有的。
    • I added records to the BelongsToCategory table, such that hat1 belonged to categories cat1 to cat5, hat2 belonged to cat1 only, and hat3 belonged to categories cat1 to cat4 and also to cat6.我在BelongsToCategory表中添加了记录,因此 hat1 属于类别 cat1 到 cat5,hat2 只属于 cat1,而 hat3 属于类别 cat1 到 cat4 以及 cat6。
  • I ran the above SQL code.我运行了上面的 SQL 代码。

When I ran the above SQL code, it returned the record for hat1.当我运行上面的 SQL 代码时,它返回了 hat1 的记录。 Job done.任务完成。 Not so fast.., When I tried playing around with it a little, changing the 5 to a 4, or a 3, 2, etc, I kept getting the record for hat1.没那么快..,当我试着玩一下,把 5 换成 4,或者 3、2 等等,我一直在获得 hat1 的记录。 and nothing else, It was only when I got to 1 that hat3 started popping up.仅此而已,只有当我到达 1 时,hat3 才开始弹出。 and I never saw hat2.我从来没有见过hat2。

What's going here?这是怎么回事? Is there something wrong with my query?我的查询有问题吗? Or is this a bug in the SQLite browser?或者这是 SQLite 浏览器中的错误?

What I Want to Know我想知道的

  • Is the above SQL query correct?上面的 SQL 查询是否正确?
  • How might it be improved?如何改进?

I don't believe that there is anything wrong with your query (I've tested it and it works as expected).我不认为您的查询有任何问题(我已经对其进行了测试,并且可以按预期工作)。 As such I believe you might not be inserting the data as expected.因此,我相信您可能没有按预期插入数据。

If you add the count sub query as an additional column to the main query and use >= 0 you can see the counts and see what is going on count wise如果您将计数子查询作为附加列添加到主查询并使用 >= 0 您可以查看计数并查看计数情况

eg :-例如:-

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
;

The following was used to test the above:-以下用于测试上述内容:-

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
;

The result of the above (using >=0):-上述结果(使用> = 0): -

在此处输入图像描述

(using >=5):- (使用 >=5):-

在此处输入图像描述

(using >=4):- (使用 >=4):-

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM