【问题标题】:Sub-selects in SQLiteSQLite 中的子选择
【发布时间】:2021-03-19 20:56:28
【问题描述】:

问题

我最近完成了一项技术测试,这要求我执行一个相当复杂的 SQL 查询,我想在收到任何反馈之前知道答案是否我给出的是正确的,以及如何改进它。

这是我对问题的解释

假设我们有一个销售帽子的网站,我们想为它建立一个数据库。每种类型的帽子都有尺寸、价格等。每种类型的帽子也可以分为无、一个或多个类别,这些类别本身可以是公共的或私有的。

执行以下操作:

  1. 编写伪 SQL 代码,创建对上述建模所需的表。
  2. 编写一个查询,该查询将返回属于至少 5 个公共类别的帽子类型的记录。

我的尝试

由于我的大部分经验是使用 SQLite,我从 SQLite 的角度解决了这个问题,并在我的回答中的评论中写了这个。

关于上面的第 (1) 点,我创建了三个表:HatCategoryBelongsToCategory,最后一个是前两个的连接表。我将public 设为Category 表的列,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 文件。
  • 我使用 Database Browser for SQLite 打开了上述文件。
  • 如上所述,我创建了我的表。
  • 我向这些表中添加了数据,如下所示:
    • 我在Hat 表中添加了三个新记录:hat1、hat2 和 hat3。
    • 我在Category 表中添加了六个新记录:cat1 到 cat6,其中 cat1 到 cat5 是公共的,而 cat6 是私有的。
    • 我在BelongsToCategory表中添加了记录,使得hat1属于cat1到cat5类别,hat2只属于cat1,hat3属于cat1到cat4类别,也属于cat6。
  • 我运行了上面的 SQL 代码。

当我运行上面的 SQL 代码时,它返回了 hat1 的记录。任务完成!没那么快...当我试着玩弄它,将 5 更改为 4,或 3、2 等时,我不断获得 hat1 的记录,没有别的。到了 1 的时候,hat3 才开始弹出来,我从来没有看到 hat2。

这是怎么回事? 我的查询有问题吗?或者这是 SQLite 浏览器中的错误?

我想知道的

  • 上面的 SQL 查询是否正确?
  • 如何改进?

【问题讨论】:

  • 您能否在小提琴中重现该问题:dbfiddle.uk/?rdbms=sqlite_3.27
  • 请在示例数据中添加表格结构。
  • 您的方法似乎合理,但对于单个 Stack Overflow 问题而言,整体问题似乎过于宽泛。

标签: sql sqlite subquery


【解决方案1】:

我认为您的查询没有任何问题(我已经对其进行了测试,它可以按预期工作)。因此,我相信您可能没有按预期插入数据。

如果您将计数子查询作为附加列添加到主查询并使用 >= 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):-

【讨论】:

    猜你喜欢
    • 2013-05-28
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-14
    • 2011-01-02
    相关资源
    最近更新 更多