【问题标题】:how to do advanced filtering of database entity by their 'tag' attritube如何通过“标签”属性对数据库实体进行高级过滤
【发布时间】:2019-07-22 06:41:40
【问题描述】:

被这个问题困扰了一段时间,非常感谢您的建议

假设我在这里有一个个人博客数据库:

第一个表:

CREATE TABLE posts(
pid TINYINT,
content TEXT,
PRIMARY KEY (pid)
);

第二张桌子:

CREATE TABLE tags(
pid TINYINT,
tag VARCHAR(16),
PRIMARY KEY (pid, tag),
FOREIGN KEY (tag) REFERENCES posts(pid)
);

然后说 他们有一些数据,比如

tags

------------------------------
pid             |          tag
1               |            a
1               |            b
1               |            d

2               |            a
2               |            c                          

我想允许客户端(用户)进行“高级过滤”

喜欢使用SELECT pid FROM tags WHERE tag `MATCHES` a && ( b || c ) && !d 完全匹配pid 2

【问题讨论】:

  • 很难。很多加盟。讨论EAV topic on this link
  • 非常有趣,似乎我发现通过使用 UNION、INTERSECT 和 MINUS,我们至少能够以一种简单的方式证明这一点。就像SELECT pid FROM tags WHERE tag ='a' INTERSECT (SELECT pid FROM tags WHERE tag='b' UNION SELECT pid FROM tags WHERE tag = 'c') INTERSECT ( ( SELECT DISTINCT pid FROM tags) MINUS (SELECT pid FROM tags WHERE tag='d'))。也就是说,` && -> 相交,|| -> 联合,! -> 全部减号 $var`

标签: mysql database-design relational-database entity-attribute-value


【解决方案1】:

WHERE tagMATCHESa && ( b || c ) && !d 的一个相当直接的映射是

WHERE     ( EXISTS SELECT 1 FROM tags WHERE pid = a.pid AND tag = 'a' )
  AND     ( EXISTS SELECT 1 FROM tags WHERE pid = a.pid AND tag IN ('b', 'c') )
  AND NOT ( EXISTS SELECT 1 FROM tags WHERE pid = a.pid AND tag = 'd' )

但是,由于它是多个相关的子查询,因此无法很好地扩展。这可能在几千行中运行良好,但如果您需要数百万行,那么我们需要讨论更复杂的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多