我有带有此类表的MySql数据库:
PageviewEvents:
pageviewId | eventId | eventValue | eventTime
SessionPageviews:
id | sessionId | page
PageviewEvents.pageviewId是将SessionPageviews.id称为外键。
当我需要通过eventId选择一些数据时,我使用以下查询:
SELECT
sp.page as Page, count(*)
from PageviewEvents pe
left join SessionPageviews sp on sp.id = pe.pageviewId
where pe.eventId = 1
GROUP by sp.page
order BY 2 DESC
并获得一个这样的表:
page | count_of_event_1
但是现在我需要选择更多数据:
page | count_of_event_1 | count_of_event_2 ... | count_of_event_N
我从2个事件开始,并尝试白色的东西:
SELECT
sp.page as Page,
(SELECT count(*) from PageviewEvents pe1 left join SessionPageviews sp1 on sp1.id = pe1.pageviewId where pe1.eventId = 1 and sp1.page = sp.page) as count_of_event_1,
(SELECT count(*) from PageviewEvents pe1 left join SessionPageviews sp1 on sp1.id = pe1.pageviewId where pe1.eventId = 2 and sp1.page = sp.page) as count_of_event_2
from PageviewEvents pe
left join SessionPageviews sp on sp.id = pe.pageviewId
where pe.eventId = 1 OR pe.eventId = 2
GROUP by sp.page
order BY 2 DESC
当我在远程服务器上运行此查询时,它冻结。
我的查询中是否有任何错误?如何优化它?
答案 0 :(得分:2)
您可以尝试使用条件聚合:
SELECT
sp.page AS Page,
COUNT(CASE WHEN pe.eventId = 1 THEN 1 END) AS count_of_event_1,
COUNT(CASE WHEN pe.eventId = 2 THEN 1 END) AS count_of_event_2
FROM PageviewEvents pe
LEFT JOIN SessionPageviews sp
ON sp.id = pe.pageviewId
WHERE
pe.eventId IN (1, 2)
GROUP BY
sp.page
ORDER BY
2 DESC;
除上述内容外,您还可以考虑在表中添加以下索引:
CREATE INDEX idx ON SessionPageviews (pageviewId, eventId);
这可能有助于加快两个表之间的连接。
答案 1 :(得分:1)
首先,您的查询可疑。您使用的是LEFT JOIN
,但是您正在按 second 表中的一列进行汇总。我怀疑您是否真的想在第一列中插入NULL
。
您可以使用条件聚合(如Tim所指出的)编写查询。我可以这样表示:
select sp.page as Page,
sum( pe.eventid = 1 ) as count_of_event_1,
sum( pe.eventid = 1 ) as count_of_event_2
from SessionPageviews sp join
PageviewEvents pe
on sp.id = pe.pageviewId
where pe.eventId in (1, 2)
group by sp.page
order by 2 desc;
然后对于此查询,有两种索引策略。如果您有多种类型的事件(或者1和2相对少见),则:
SessionPageviews(id, page)
PageviewEvents(eventId, pageviewId)
否则:
SessionPageviews(page, id)
PageviewEvents(pageviewId, eventId)