是否可以合并这些(长)mysql查询?

时间:2008-12-03 07:59:17

标签: mysql

好吧,我的困境就是这个。我有一个管理页面,用于获取当天提​​交给我的某个网站的摘要。此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),这需要一段时间来生成页面。

5 个答案:

答案 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