我有这样的查询:
SELECT u.id, u.name, top_tags(u.id) as top_tags, cal_rep(u.id) rep
FROM users
ORDER BY rep
LIMIT :p,20;
top_tags()
是一个函数,它返回NULL
或逗号分隔的用户前三个标记字符串。此外,cal_rep()
是另一个返回0
或声誉数量的函数。因此,上面的查询始终返回所有用户的列表。像这样:
+----+----------+-------------------------------+-----------+
| id | name | top_tags | rep |
+----+----------+-------------------------------+-----------+
| 1 | Jack | HTML,CSS,jQuery | 3244 |
| 2 | Peter | SQL-Server,MySQL,Database | 543 |
| 3 | Martin | NULL | 0 |
+----+----------+-------------------------------+-----------+
虽然我想省略NULL
作为top_tags
和0
声誉的用户。所以这是预期的结果:
+----+----------+-------------------------------+-----------+
| id | name | top_tags | rep |
+----+----------+-------------------------------+-----------+
| 1 | Jack | HTML,CSS,jQuery | 3244 |
| 2 | Peter | SQL-Server,MySQL,Database | 543 |
+----+----------+-------------------------------+-----------+
我该怎么做?
答案 0 :(得分:1)
您可以在WHERE子句中使用相同的表达式。
SELECT u.id, u.name, top_tags(u.id) as top_tags, cal_rep(u.id) rep
FROM users
WHERE top_tags(u.id) IS NOT NULL
AND cal_rep(u.id) <> 0
ORDER BY rep
LIMIT :p,20;
不确定您是否需要AND
或OR
。
如果您不想重复SELECT子句中的表达式,可以在HAVING子句中使用它们的别名。
SELECT u.id, u.name, top_tags(u.id) as top_tags, cal_rep(u.id) rep
FROM users
HAVING top_tags IS NOT NULL
AND rep <> 0
ORDER BY rep
LIMIT :p,20;
关于性能:在一个包含100万个整数序列的表上,我测试了以下查询(MySQL 5.7.18):
select i
from helper.seq
-- 0.265 sec
select length(sha2(sha2(i, 512), 512)) as l
from helper.seq
-- 1.843 sec
select length(sha2(sha2(i, 512), 512)) as l
from helper.seq
where length(sha2(sha2(i, 512), 512)) = 128
-- 3.437 sec
select length(sha2(sha2(i, 512), 512)) as l
from helper.seq
having l = 128
-- 3.531 sec
select *
from (
select length(sha2(sha2(i, 512), 512)) as l
from helper.seq
) sub
where l = 128
-- 3.547 sec
比较前两个查询,我们可以看到嵌套函数调用的开销约为1.6秒。对于其他三个查询,我们看到相同的开销加倍。我不知道幕后发生了什么,但看起来MySQL无论采用何种方法都会执行两次。
答案 1 :(得分:1)
使用WHERE
子句和is null
运算符。
答案 2 :(得分:0)
select *
from (
SELECT u.id, u.name, top_tags(u.id) as top_tags, cal_rep(u.id) rep
FROM users
LIMIT :p,20
) a
where a.top_tags is not null
and a.rep != 0
ORDER BY a.rep;
这样,函数只执行一次。