我的查询是这样的:
SELECT date_format( created_at, '%Y-%m-%d' ) AS the_date,
COUNT(s.id) AS total,
(SELECT COUNT(ks.id) FROM kc_shares ks WHERE site = 'facebook' AND date_format( created_at, '%Y-%m-%d' ) = the_date ) AS total_facebook,
(SELECT COUNT(ks.id) FROM kc_shares ks WHERE site = 'twitter' AND date_format( created_at, '%Y-%m-%d' ) = the_date ) AS total_twitter
FROM `kc_shares` s
GROUP BY `the_date`
我想得到的是每日股票的数量,包括总数,Facebook总份额(因此site ='facebook')和twitter的总股数。这就是我需要GROUP BY
。
当它有几千行时,没有问题。但该表目前有近20万行,查询速度很慢,大约需要20-30秒,我想更多。
我尝试在site和created_at字段中添加索引,但无济于事。
由于
答案 0 :(得分:1)
移动子选择,以便您加入它们,而不是为每个返回的行执行子选择。
像这样(未经测试): -
SELECT date_format( created_at, '%Y-%m-%d' ) AS the_date,
COUNT(s.id) AS total,
Sub1.total_facebook, Sub2.total_twitter
FROM `kc_shares` s
LEFT OUTER JOIN (SELECT date_format( created_at, '%Y-%m-%d' ) AS sub_date, COUNT(ks.id) AS total_facebook FROM kc_shares ks WHERE site = 'facebook' GROUP BY sub_date ) Sub1 ON date_format( created_at, '%Y-%m-%d' ) = Sub1.sub_date
LEFT OUTER JOIN (SELECT date_format( created_at, '%Y-%m-%d' ) AS sub_date, COUNT(ks.id) AS total_twitter FROM kc_shares ks WHERE site = 'twitter' GROUP BY sub_date ) Sub2 ON date_format( created_at, '%Y-%m-%d' ) = Sub2.sub_date
GROUP BY `the_date`
虽然找到一种在非派生列上进行连接的方法(即日期/时间的日期部分)也会有所帮助。这可能是一个很好的例子,用于一点或非规范化,只为日期和时间添加一个字段添加到当前存储的日期/时间。
答案 1 :(得分:1)
我认为子查询正在消耗性能。所以也许你可以这样做:
SELECT
date_format( created_at, '%Y-%m-%d' ) AS the_date,
COUNT(s.id) AS total,
SUM(CASE WHEN s.site='facebook' THEN 1 ELSE 0 END) AS total_facebook,
SUM(CASE WHEN s.site='twitter' THEN 1 ELSE 0 END) AS total_twitter
FROM
`kc_shares` s
GROUP BY
`the_date
`
答案 2 :(得分:0)
另一种方法是更改查询的工作方式。以下内容将为每天/站点提供行,而不是将两个站点放在同一行上。
SELECT
date_format( created_at, '%Y-%m-%d' ) AS the_date,site,
count(id)
FROM
kc_shares s
where
(site="facebook" or site="twitter") )
group by
created_at, site
我假设created_at是一个日期字段。
这应该提供相同的数据(我想,我还没有尝试过),但是格式不同。
在(created_at,site)上尝试索引。