【发布时间】:2010-05-16 20:40:14
【问题描述】:
我正在尝试优化 Akonadi 中的 SQL 查询,但遇到了以下问题,至少对我而言,SQL 显然不容易解决:
假设如下表结构(应该适用于 SQLite、PostgreSQL、MySQL):
CREATE TABLE a (
a_id INT PRIMARY KEY
);
INSERT INTO a (a_id) VALUES (1), (2), (3), (4);
CREATE TABLE b (
b_id INT PRIMARY KEY,
a_id INT,
name VARCHAR(255) NOT NULL
);
INSERT INTO b (b_id, a_id, name)
VALUES (1, 1, 'foo'), (2, 1, 'bar'), (3, 1, 'asdf'),
(4, 2, 'foo'), (5, 2, 'bar'), (6, 3, 'foo');
现在我的问题是在a 中查找表b 中缺少name 条目的条目。例如。我需要确保a 中的每个条目至少在表b 中具有name 条目"foo" 和"bar"。因此查询应该返回类似于:
a_id = 3 is missing name "bar"
a_id = 4 is missing name "foo" and "bar"
由于在 Akonadi 中这两个表都可能很大,因此性能至关重要。
MySQL 中的一个解决方案是:
SELECT a.a_id,
CONCAT('|', GROUP_CONCAT(name ORDER BY NAME ASC SEPARATOR '|'), '|') as names
FROM a
LEFT JOIN b USING( a_id )
GROUP BY a.a_id
HAVING names IS NULL OR names NOT LIKE '%|bar|foo|%';
我还没有衡量明天的表现,但我严重怀疑a 中的数万条条目和b 中的三倍之多是否很快。此外,我们希望支持 SQLite 和 PostgreSQL,据我所知,GROUP_CONCAT 函数不可用。
谢谢,晚安。
【问题讨论】:
-
我可以问为什么单引号是“更好”的 araqnid?
-
单引号是sql中引用字符串的标准。例如,用于填充表的示例脚本没有在 postgresql 中运行。众所周知,Mysql 允许这样的事情。不确定sqlite。据我所知,Sql server 和 oracle 没有。
-
这就是为什么 EAV 是一种反模式
标签: sql mysql sqlite postgresql