2017-07-30 7 views
0

私はこのようなクエリがある:select文の値に基づいてどのように結果を制限できますか?

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またはユーザーの上位3つのタグのカンマで区切られた文字列のいずれかを返す関数です。また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   | 
+----+----------+-------------------------------+-----------+  

私は彼らのtop_tags0評判としてNULLを持つユーザーを省略したいものの。したがって、これは期待される結果です。

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

どうすればいいですか?

答えて

1

WHERE句で同じ式を使用できます。あなたがANDORをしたい場合はわからない

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; 

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; 

:私は次のクエリ(MySQLの5.7.18)をテストしている100万個の整数の配列とテーブルの上に:最初の2つのクエリを比較すると

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秒です。他の3つのクエリについては、同じオーバーヘッドが倍増しています。舞台裏で何が起こっているのか分かりませんが、MySQLがメソッドに関係なく関数を2回実行するようです。

+0

ありがとうございます...あなたの最初のクエリは最適だと思いますか?関数を2回呼び出すので両方とも 'SELECT'ステートメントと' WHERE'節で。 –

+0

ベンチマークに基づいて、関数の結果を変数に初期化し、その変数をクエリで2回使用する方が良いでしょう。 –

1

オペレータWHEREとオペレータis nullを使用してください。

+0

ありがとう.. upvote –

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; 

こうして、関数は1回だけ実行されます。

+0

あなたは同じトリック[ここ](https://stackoverflow.com/a/45403564/5563083)を試してみました。これは、フィルタリングする前に結果を制限しているため、期待どおりに機能しません。 –

関連する問題