此查询根据子查询中的COUNT列计算列free
,plus
,score
和total
。
SELECT movie_title,movie_id,MAX(x.free_cnt) as free, MAX(x.plus_cnt) as plus,
(MAX(x.free_cnt) + (MAX(x.plus_cnt)*3)) AS score, (MAX(x.free_cnt) + MAX(x.plus_cnt)) AS total
FROM (
SELECT b.id as movie_id, b.movie_title as movie_title, COUNT(*) AS free_cnt, 0 as plus_cnt
FROM subtitles_request a1
LEFT JOIN movies b on a1.movie_id=b.id
JOIN users c on c.email=a1.email
WHERE c.subsc_status='0'
GROUP BY b.movie_title
UNION ALL
SELECT d.id as movie_id, d.movie_title as movie_title, 0 as free_cnt, COUNT(*) AS plus_cnt
FROM subtitles_request a2
LEFT JOIN movies d on a2.movie_id=d.id
JOIN users e on e.email=a2.email
WHERE e.subsc_status='1'
GROUP BY d.movie_title
) AS x
GROUP BY movie_title
ORDER BY total DESC
LIMIT 10
执行速度很慢,我想知道是否仍然可以简化或更改查询以提高性能。由于能够排序,我无法计算查询之外的free
,plus
,score
,total
列。我也可以加入日期。
是否可以简化此查询?
答案 0 :(得分:1)
尝试一下:
SELECT b.movie_title, x.movie_id, MAX( x.free_cnt ) AS free, MAX( x.plus_cnt ) AS plus,
( MAX( x.free_cnt ) + ( MAX( x.plus_cnt ) * 3 ) ) AS score, ( MAX( x.free_cnt ) + MAX( x.plus_cnt ) ) AS total
FROM ( SELECT a.movie_id,
SUM( IF( c.subsc_status = '0', 1, 0 ) ) AS free_cnt,
SUM( IF( c.subsc_status = '1', 1, 0 ) ) AS plus_cnt
FROM subtitles_request a1
JOIN users c on c.email=a1.email
WHERE c.subsc_status in ('0','1')
GROUP BY a.movie_id
) AS x
LEFT JOIN movies b on x.movie_id = b.id
GROUP BY movie_title, movie_id
ORDER BY total DESC
LIMIT 10
也许我简化了太多。此外,我不习惯仅对一些非聚合字段进行分组,因此我在要分组的内容上添加了movie_id,从而稍微更改了您的查询(如果两部电影的名称相同,但ID不同,则您原来的查询中只会返回一个ID,但是我猜(我是MySQL的新手,我真的不知道)这两个ID的计数是合计的。
HTH, 设置
答案 1 :(得分:0)
好吧,我已经检查了您的子查询:
(defstruct comment style string)
(defstruct whitespace string)
(defconstant +whitespace-chars+ '(#\Space #\Tab #\Return #\Newline))
(defconstant +eof+ (gensym "EOF"))
(defun read-semicolon-comment (stream semicolon)
(declare (ignore semicolon))
(make-comment :style :semicolon :string
(with-output-to-string (comment)
(loop (let ((char (read-char stream nil +eof+ t)))
(cond ((equal char +eof+) (return))
((equal char #\Newline)
(unread-char char stream)
(return))
(t (write-char char comment))))))))
(defun read-whitespace (stream first-char)
(make-whitespace :string
(with-output-to-string (whitespace)
(write-char first-char whitespace)
(loop (let ((char (read-char stream nil +eof+ t)))
(unless (member char +whitespace-chars+)
(unless (equal char +eof+) (unread-char char stream))
(return))
(write-char char whitespace))))))
(defun read-stream (stream)
(with-standard-io-syntax ; Here's a comment, for example.
(let ((*readtable* (copy-readtable)))
(set-macro-character #\; #'read-semicolon-comment)
(dolist (char +whitespace-chars+)
(set-macro-character char #'read-whitespace))
(loop for x = (read stream nil +eof+) until (equal x +eof+)
collect x))))
(defmethod print-object ((x comment) stream)
(assert (equal :semicolon (comment-style x)))
(write-char #\; stream)
(write-string (comment-string x) stream)
x)
(defmethod print-object ((x whitespace) stream)
(write-string (whitespace-string x) stream)
x)
(mapc #'prin1 (read-stream *standard-input*))
“ UNION ALL”旁边的语句可以替换为条件为SELECT b.id as movie_id, b.movie_title as movie_title, COUNT(*) AS free_cnt, 0 as plus_cnt
FROM subtitles_request a1
LEFT JOIN movies b on a1.movie_id=b.id
JOIN users c on c.email=a1.email
WHERE c.subsc_status='0'
GROUP BY b.movie_title
UNION ALL
SELECT d.id as movie_id, d.movie_title as movie_title, 0 as free_cnt, COUNT(*) AS plus_cnt
FROM subtitles_request a2
LEFT JOIN movies d on a2.movie_id=d.id
JOIN users e on e.email=a2.email
WHERE e.subsc_status='1'
GROUP BY d.movie_title
的一条语句。您可以尝试在c.subsc_status IN('0','1')
上使用“ CASE WHEN”语句,就像0 as free_cnt, COUNT(*) AS plus_cnt
一样。这不是复杂的sql语句,我认为查询不会花费太多时间。数据太多了吗?
事实上,我也是新手,但是我对此有一些了解。如果它不起作用,请原谅我。