【问题标题】:Querying with an arbitrary boolean expression on a join table在连接表上使用任意布尔表达式进行查询
【发布时间】:2018-09-27 17:04:45
【问题描述】:

我正在尝试对 itemtag 表之间的多对多关系建模。我有一个连接表tagitemjoin 来完成它。例如:

 id | tag_id | item_id
-----------------------
  1 |    1   |    1
  2 |    2   |    1
  3 |    2   |    2
  4 |    3   |    1
  5 |    3   |    2
  6 |    3   |    3
  7 |    4   |    2
  8 |    4   |    3
  9 |    5   |    3

代表以下连接

       | item: 1 | item: 2 | item: 3
-------------------------------------
tag: 1 |    *    |         |
tag: 2 |    *    |    *    |
tag: 3 |    *    |    *    |    *
tag: 4 |         |    *    |    *
tag: 5 |         |         |    *

我希望根据涉及tags 的任意布尔表达式查询items 的列表,例如:

tag1 OR ((NOT tag2) AND tag3)

由于我需要实现 3 个基本运算符,因此我能够实现 OR,如下所示:

SELECT i.* FROM item i
           INNER JOIN tagitemjoin j
           ON (j.item_id = i.id)
           WHERE (j.tag_id = 3) OR (j.tag_id = 4) GROUP BY i.id

而且我确信我也可以以某种方式使用COUNT 实现NOTAND 运算符。不过……

如何扩展此定义以处理任意布尔表达式?使用这种连接表方法可以做到这一点吗?

如果没有,我可能会使用 NoSQL 方法将 tags 作为集合存储在 items 字典本身中,因为该方法更直接。

【问题讨论】:

    标签: sql database join sqlite


    【解决方案1】:

    用子查询替换连接允许以更自然的方式编写布尔表达式:

    WITH tag1 AS (SELECT item_id FROM tagitemjoin WHERE tag_id = 1),
         tag2 AS (SELECT item_id FROM tagitemjoin WHERE tag_id = 2),
         tag3 AS (SELECT item_id FROM tagitemjoin WHERE tag_id = 3)
    SELECT * FROM item
    WHERE id IN tag1 OR (id NOT IN tag2 AND id IN tag3);
    

    【讨论】:

      【解决方案2】:

      为此,我喜欢 group byhaving。例如,对于标签 3 或 4:

      select tij.item_id
      from tagitemjoin tij
      group by tij.item_id
      having sum(case when tij.tag_id = 3 then 1 else 0 end) > 0 or
             sum(case when tij.tag_id = 4 then 1 else 0 end) > 0;
      

      sum(case . . . ) 计算标签出现的项目数。然后条件使用> 0 表示标签存在; = 0 将用于指定标签不存在。

      这个框架是相当普遍的。它可以用于标签的任何布尔组合。

      【讨论】:

      • 我明白了。非常感谢你的帮助。现在我只需要尝试创建一个模板来构建这些。
      • @sshashank124 。 . .您是否有理由不接受此答案?
      • 我只是更喜欢另一个答案的方法,因为它更加模块化和可读
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-30
      • 2017-03-02
      • 2019-10-07
      • 2013-10-14
      • 1970-01-01
      • 2010-09-21
      • 1970-01-01
      相关资源
      最近更新 更多