sql - Mysql, get rows before specific row in a multi-column index -
say have table high-scores:
id : primary key username : string score : int
user names , scores can repeating, id unique each person. have index high-scores fast:
unique scores ( score, username, id )
how can rows below given person? 'below' mean go before given row in index.
e.g. ( 77, 'name7', 70 ) in format ( score, username, id ) want retrieve:
77, 'name7', 41 77, 'name5', 77 77, 'name5', 21 50, 'name9', 99
but not
77, 'name8', 88 or 77, 'name7', 82 or 80, 'name2', 34 ...
here's 1 way result:
select t.score , t.username , t.id scores t ( t.score < 77 ) or ( t.score = 77 , t.username < 'name7' ) or ( t.score = 77 , t.username = 'name7' , t.id < 70 ) order t.score desc , t.username desc , t.id desc
(note: order clause may mysql decide use index avoid "using filesort
" operation. index "covering" index query, we'd expect see "using index
" in explain
output.)
i ran quick test, , in environment, perform range scan of index , avoids sort operation.
explain output
id select_type table type possible_keys key rows -- ----------- ----- ----- ------------------ ---------- ---- -------------------------- 1 simple t range primary,scores_ux1 scores_ux1 3 using where; using index
(you may want add limit n
query, if don't need return rows satisfy criteria.)
if have unique id of row, avoid specifying values in table doing join. given data in question:
here use second reference same table, row id=70, , join rows "lower".
select t.score , t.username , t.id scores k join scores t on ( t.score < k.score ) or ( t.score = k.score , t.username < k.username ) or ( t.score = k.score , t.username = k.username , t.id < k.id ) k.id = 70 order t.score desc , t.username desc , t.id desc limit 1000
the explain query shows mysql using covering index , avoiding sort operation:
id select_type table type possible_keys key rows -- ----------- ----- ----- ------------------ ---------- ---- ------------------------ 1 simple k const primary,scores_ux1 primary 1 1 simple t range primary,scores_ux1 scores_ux1 3 using where; using index
Comments
Post a Comment