好吧,我的困境就是这个。我有一个管理页面,用于获取当天提交给我的某个网站的摘要。此sumamry页面从几个表中提取数据,其中一些表存储实际的媒体数据,其他表存储网站URL,ID和所有者,另一个表存储日常统计数据以计算每个域的输入/输出比率。
此管理页面有一个主查询,它会提取实际的媒体数据,如下所示(简化):
SELECT
content.con_catid,
content.con_posttime,
content.con_url,
content.con_id,
content.con_title,
categories.name,
users.username,
users.user_id,
FROM content
LEFT JOIN categories
ON (content.con_catid = categories.id)
LEFT JOIN users
ON (content.con_poster = users.user_id)
WHERE con_status = 0 ORDER BY con_posttime
相当直接。然后,这就是它变得凌乱的地方。每次循环mysql_fetch_array语句(输出每个内容项),我也运行这两个查询:
SELECT count(con_id) as pending FROM content WHERE con_poster = '$this_userid' AND con_status = 0
SELECT count(con_id) as approved FROM content WHERE con_poster = '$this_userid' AND con_status = 2
这些获取拥有提交的每个用户的待处理和已批准项目的数量(列在每个提交的旁边。
然后有杀手,它增加了大量的页面执行时间,因为它也必须为初始查询的每一行重复。
SELECT website_url,
website_id,
website_shady,
COALESCE(sum(dstats_hits),0)+website_in_ballast as total_in,
COALESCE(sum(dstats_hits_out),0)+website_out_ballast as total_out,
sum(dstats_hits_out_paid) as total_paid,
website_in_ballast,
website_out_ballast
FROM websites
LEFT JOIN domain_stats ON (websites.website_id = domain_stats.dstats_domid)
WHERE website_id IN (SELECT website_id FROM websites WHERE website_userid = $this_userid)
GROUP BY website_url
有没有什么方法可以合并后一个3个查询?因为现在......如果队列中有100个项目,那就是301查询(如果包含子查询则为401),这需要一段时间来生成页面。
答案 0 :(得分:0)
我还没有考虑到第三个额外的查询,但对于前两个,你可以做类似的事情:
SELECT count(con_id) as pending, con_poster FROM content
WHERE con_status = 0
GROUP BY con_poster
然后将它们与con_poster上的第一个查询联系起来。
答案 1 :(得分:0)
这个功能对我来说很方便,也许它对你有帮助。 您可以将查询用作选择之一。
SELECT
col_1,
col_2,
col_3,
(
SELECT col_1
FROM table_2
WHERE table_2.col_2 = table_1.col_1
) as 'col4',
col_5
FROM
table_1
完全合法。
答案 2 :(得分:0)
嗯......第一个查询只选择内容项,而其他查询则选择一些关于它们的统计信息。第一个查询不使用任何聚合函数,而所有其他函数都使用。因此,我能看到你加入它们的唯一方法是使用子查询。它不会使执行计划更好,但它将为您节省数百个查询解析和结果集生成,因此它应该更快一些。
虽然有一个提示 - 中间两个查询可以像这样连接在一起:
SELECT
count(case when con_status=0 then 1 else null end) as pending,
count(case when con_status=2 then 1 else null end) as approved
FROM
content
WHERE
con_poster = '$this_userid'
答案 3 :(得分:0)
为特定的user_id再次加入内容将使您有可能进行计数。
SELECT content.con_catid, content.con_posttime, content.con_url, content.con_id, content.con_title, categories.name, users.username, users.user_id, IFNULL(SUM(CASE WHEN c2.con_status = 0 THEN 1 ELSE 0 END), 0) as pending, IFNULL(SUM(CASE WHEN c2.con_status = 2 THEN 1 ELSE 0 END), 0) as approved FROM content LEFT JOIN categories ON (content.con_catid = categories.id) LEFT JOIN users ON (content.con_poster = users.user_id) LEFT JOIN content as c2 ON users.user_id = c2.con_poster WHERE con_status = 0 GROUP BY content.con_id ORDER BY con_posttime
这是未经测试的。您可以连接两次内容并使用COUNT(DISTINCT c2.con_id)AS pending和COUNT(DISTINCT c3.con_id)AS批准,如果CASE语句要慢,那么在连接中添加c2.con_status = 0条款(待定职位)。
如果您没有任何帖子(由于主要内容行始终存在,因此永远不会是真的,因此,IFNULL是存在的。如果您不想计算,您可以禁止JOIN条款中的当前帖子它)。
对于最后一个查询,我会为您正在处理的所有用户选择所有信息(保存所有ID,然后使用user_id IN()代替或者使用子选择(取决于您如何进行选择)。< / p>
然后在代码中对数据进行排序和处理。这最大限度地减少了查询次数。
答案 4 :(得分:0)
这是另一个尝试将其变成一个巨大的查询。不知道它有多快......
编辑:好的,第三次尝试。如果设置正确的索引,这实际上应该非常快。
SELECT
content.con_catid,
content.con_posttime,
content.con_url,
content.con_id,
content.con_title,
categories.name,
users.username,
users.user_id,
stats1.website_url,
websites.website_id,
websites.website_shady,
websites.website_in_ballast,
websites.website_out_ballast,
(SELECT COALESCE(sum(dstats_hits),0)+website.website_in_ballast FROM domain_stats WHERE websites.website_id = domain_stats.dstats_domid) as total_in,
(SELECT COALESCE(sum(dstats_hits_out),0)+website_out_ballast FROM domain_stats WHERE websites.website_id = domain_stats.dstats_domid) as total_out,
(SELECT sum(dstats_hits_out_paid) FROM domain_stats WHERE websites.website_id = domain_stats.dstats_domid) as total_paid,
(SELECT count(c2.con_id) FROM content c2 WHERE c2.con_poster = user.user_id AND con_status = 0) as pending,
(SELECT count(c2.con_id) FROM content c2 WHERE c2.con_poster = user.user_id AND con_status = 2) as approved
FROM
content
LEFT JOIN categories ON (content.con_catid = categories.id)
LEFT JOIN users ON (content.con_poster = users.user_id)
LEFT JOIN websites ON (website_userid=users.user_id)
WHERE
con_status = 0
ORDER BY
con_posttime