如何根据select语句中的值限制结果?

时间:2017-07-30 15:46:56

标签: mysql sql

我有这样的查询:

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_tags0声誉的用户。所以这是预期的结果:

+----+----------+-------------------------------+-----------+
| id |   name   |            top_tags           |    rep    |
+----+----------+-------------------------------+-----------+
| 1  | Jack     | HTML,CSS,jQuery               | 3244      |
| 2  | Peter    | SQL-Server,MySQL,Database     | 543       |
+----+----------+-------------------------------+-----------+    

我该怎么做?

3 个答案:

答案 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;

不确定您是否需要ANDOR

如果您不想重复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;

这样,函数只执行一次。