Php 是否可以将查询数量从5减少到1?

Php 是否可以将查询数量从5减少到1?,php,mysql,sql,Php,Mysql,Sql,我有一个画廊的“领导者”在我的网站上,在5个不同类别的顶级用户是由一个描述限制1;gallery在stats表和login表之间使用5个单独的内部联接生成,但所有SELECT子句都是相同的: $cat1wins="SELECT stats.login_id, stats.cat1wins, login.user, login.picture, login.statement FROM stats INNER JOIN login ON stats.login_id=login.log

我有一个画廊的“领导者”在我的网站上,在5个不同类别的顶级用户是由一个描述限制1;gallery在stats表和login表之间使用5个单独的内部联接生成,但所有SELECT子句都是相同的:

$cat1wins="SELECT stats.login_id, stats.cat1wins, login.user, login.picture,      
login.statement FROM stats INNER JOIN login ON stats.login_id=login.login_id ORDER by 
stats.cat1wins DESC LIMIT 1";

$cat2wins="SELECT stats.login_id, stats.cat2wins, login.user, login.picture,      
login.statement FROM stats INNER JOIN login ON stats.login_id=login.login_id ORDER by 
stats.cat2wins DESC LIMIT 1";

$cat3wins="SELECT stats.login_id, stats.cat3wins, login.user, login.picture,      
login.statement FROM stats INNER JOIN login ON stats.login_id=login.login_id ORDER by 
stats.cat3wins DESC LIMIT 1";

$cat4wins="SELECT stats.login_id, stats.cat4wins, login.user, login.picture,      
login.statement FROM stats INNER JOIN login ON stats.login_id=login.login_id ORDER by 
stats.cat4wins DESC LIMIT 1";

$cat5wins="SELECT stats.login_id, stats.cat5wins, login.user, login.picture,      
login.statement FROM stats INNER JOIN login ON stats.login_id=login.login_id ORDER by 
stats.cat5wins DESC LIMIT 1";
对于每个类别,WHILE循环提取适当的表单元格(这里用cat1显示)

我想一定有更好的办法;我想我可以这样开始:

$catAllwins="SELECT stats.cat1wins, stats.login_id, login.user, login.picture,      
login.statement, SELECT stats.cat2wins, stats.login_id, login.user, login.picture, 
login.statement,.....SELECT stats.cat5wins, stats.login_id, login.user, login.picture, 
login.statement FROM stats INNER JOIN login ON stats.login_id=login.login_id";
然后对$catalwins中每个SELECT语句的结果使用WHILE循环生成5个单独的数组,然后可以使用natsort对这些数组进行排序。但是,我不确定如何提取正确的SELECT语句。我在想我可以这样说:

$catAllwins="SELECT stats.cat1wins, stats.login_id, login.user, login.picture,      
login.statement AS 'array1', SELECT stats.cat2wins, stats.login_id, login.user,    
login.picture, login.statement AS 'array2',.....SELECT stats.cat5wins, stats.login_id,  
login.user, login.picture, login.statement AS 'array5' FROM stats INNER JOIN login ON 
stats.login_id=login.login_id";

$resultAll = mysqli_query($con, $catAllwins)
$Cat1WinsArray = $resultAll['array1'];
$Cat2WinsArray = $resultAll['array2'];
$Cat3WinsArray = $resultAll['array3'];
$Cat4WinsArray = $resultAll['array4'];
$Cat5WinsArray = $resultAll['array5'];
然后使用natsort对数组进行排序(显示了一个示例)

然后按降序添加数组\u reverse

$DescSortedCat1WinsArray = array_reverse($SortedCat1WinsArray);

然后,使用此数组提取我需要的每个组件(例如,$row['picture']、$row['login_id']等)。这听起来有一点道理吗?如果有任何反馈,我将不胜感激!有更简单的方法吗?

您可以将各个select语句合并在一起,并对结果合并应用排序。以下是一个例子:

(SELECT stats.login_id, stats.cat1wins, login.user, login.picture, login.statement
FROM stats INNER JOIN login ON stats.login_id=login.login_id
ORDER by stats.cat1wins DESC LIMIT 1)
UNION
(SELECT stats.login_id, stats.cat2wins, login.user, login.picture, login.statement
FROM stats INNER JOIN login ON stats.login_id=login.login_id
ORDER by stats.cat2wins DESC LIMIT 1)
UNION
(SELECT stats.login_id, stats.cat3wins, login.user, login.picture, login.statement
FROM stats INNER JOIN login ON stats.login_id=login.login_id
ORDER by stats.cat3wins DESC LIMIT 1)
UNION
(SELECT stats.login_id, stats.cat4wins, login.user, login.picture, login.statement
FROM stats INNER JOIN login ON stats.login_id=login.login_id
ORDER by stats.cat4wins DESC LIMIT 1)
UNION
(SELECT stats.login_id, stats.cat5wins, login.user, login.picture, login.statement
FROM stats INNER JOIN login ON stats.login_id=login.login_id
ORDER by stats.cat5wins DESC LIMIT 1)
ORDER BY /* Whatever you want to sort by. Wasn't clear in the questoin */

您可以将各个select语句合并在一起,并对结果合并应用排序。以下是一个例子:

(SELECT stats.login_id, stats.cat1wins, login.user, login.picture, login.statement
FROM stats INNER JOIN login ON stats.login_id=login.login_id
ORDER by stats.cat1wins DESC LIMIT 1)
UNION
(SELECT stats.login_id, stats.cat2wins, login.user, login.picture, login.statement
FROM stats INNER JOIN login ON stats.login_id=login.login_id
ORDER by stats.cat2wins DESC LIMIT 1)
UNION
(SELECT stats.login_id, stats.cat3wins, login.user, login.picture, login.statement
FROM stats INNER JOIN login ON stats.login_id=login.login_id
ORDER by stats.cat3wins DESC LIMIT 1)
UNION
(SELECT stats.login_id, stats.cat4wins, login.user, login.picture, login.statement
FROM stats INNER JOIN login ON stats.login_id=login.login_id
ORDER by stats.cat4wins DESC LIMIT 1)
UNION
(SELECT stats.login_id, stats.cat5wins, login.user, login.picture, login.statement
FROM stats INNER JOIN login ON stats.login_id=login.login_id
ORDER by stats.cat5wins DESC LIMIT 1)
ORDER BY /* Whatever you want to sort by. Wasn't clear in the questoin */

按五个不同的变量排序是昂贵的。您可能会发现以下方法更有效:

select l.login_id,
       (case when s.cat1wins = smax.max_cat1wins then 'cat1'
             when s.cat2wins = smax.max_cat2wins then 'cat2'
             when s.cat3wins = smax.max_cat3wins then 'cat3'
             when s.cat4wins = smax.max_cat4wins then 'cat4'
             when s.cat5wins = smax.max_cat5wins then 'cat5'
         end) as which,
       (case when s.cat1wins = smax.max_cat1wins then s.cat1wins
             when s.cat2wins = smax.max_cat2wins then s.cat2wins
             when s.cat3wins = smax.max_cat3wins then s.cat3wins
             when s.cat4wins = smax.max_cat4wins then s.cat4wins
             when s.cat5wins = smax.max_cat5wins then s.cat5wins
         end) as numwins,
       l.user, l.picture, l.statement,
from stats s inner join
     (select max(stats.cat1wins) as max_cat1wins,
             max(stats.cat2wins) as max_cat2wins,
             max(stats.cat3wins) as max_cat3wins,
             max(stats.cat4wins) as max_cat4wins,
             max(stats.cat5wins) as max_cat5wins
      from stats
     ) smax
     on s.cat1wins = smax.max_cat1wins or
        s.cat2wins = smax.max_cat2wins or
        s.cat3wins = smax.max_cat3wins or
        s.cat4wins = smax.max_cat4wins or
        s.cat5wins = smax.max_cat5wins join
     login l
     on s.login_id = l.login_id;

与最初的五个查询相比,这种方式有两个重要的区别。首先,如果某人在两个或两个以上的类别中排名第一,他们在这里只出现一次。第二,如果多人在一个类别中并列最佳,那么所有人都包括在内。

按五个不同的变量排序是昂贵的。您可能会发现以下方法更有效:

select l.login_id,
       (case when s.cat1wins = smax.max_cat1wins then 'cat1'
             when s.cat2wins = smax.max_cat2wins then 'cat2'
             when s.cat3wins = smax.max_cat3wins then 'cat3'
             when s.cat4wins = smax.max_cat4wins then 'cat4'
             when s.cat5wins = smax.max_cat5wins then 'cat5'
         end) as which,
       (case when s.cat1wins = smax.max_cat1wins then s.cat1wins
             when s.cat2wins = smax.max_cat2wins then s.cat2wins
             when s.cat3wins = smax.max_cat3wins then s.cat3wins
             when s.cat4wins = smax.max_cat4wins then s.cat4wins
             when s.cat5wins = smax.max_cat5wins then s.cat5wins
         end) as numwins,
       l.user, l.picture, l.statement,
from stats s inner join
     (select max(stats.cat1wins) as max_cat1wins,
             max(stats.cat2wins) as max_cat2wins,
             max(stats.cat3wins) as max_cat3wins,
             max(stats.cat4wins) as max_cat4wins,
             max(stats.cat5wins) as max_cat5wins
      from stats
     ) smax
     on s.cat1wins = smax.max_cat1wins or
        s.cat2wins = smax.max_cat2wins or
        s.cat3wins = smax.max_cat3wins or
        s.cat4wins = smax.max_cat4wins or
        s.cat5wins = smax.max_cat5wins join
     login l
     on s.login_id = l.login_id;
与最初的五个查询相比,这种方式有两个重要的区别。首先,如果某人在两个或两个以上的类别中排名第一,他们在这里只出现一次。其次,如果多人在一个类别中并列最佳,则所有人都包括在内。

获取每个最大类别的用户ID

这个怎么样?这没有
分组依据
,只需要1次完整扫描

    SELECT
        IF(cat1wins >= @mxc1, @mxu1 := login_id, @mxu1) AS userid1,
        IF(cat1wins >= @mxc1, @mxc1 := cat1wins, @mxc1) AS max_cat1wins,

        IF(cat2wins >= @mxc2, @mxu2 := login_id, @mxu2) AS userid2,
        IF(cat2wins >= @mxc2, @mxc2 := cat2wins, @mxc2) AS max_cat2wins,

        IF(cat3wins >= @mxc3, @mxu3 := login_id, @mxu3) AS userid3,
        IF(cat3wins >= @mxc3, @mxc3 := cat3wins, @mxc3) AS max_cat3wins,

        IF(cat4wins >= @mxc4, @mxu4 := login_id, @mxu4) AS userid4,
        IF(cat4wins >= @mxc4, @mxc4 := cat4wins, @mxc4) AS max_cat4wins,

        IF(cat5wins >= @mxc5, @mxu5 := login_id, @mxu5) AS userid5,
        IF(cat5wins >= @mxc5, @mxc5 := cat5wins, @mxc5) AS max_cat5wins
    FROM stats, (
        SELECT
          @mxc1 := 0, @mxc2 := 0, @mxc3 := 0, @mxc4 := 0, @mxc5 := 0,
          @mxu1 := 0, @mxu2 := 0, @mxu3 := 0, @mxu4 := 0, @mxu5 := 0
    ) x;
最后,我们使用join with login table获取登录信息

请注意,下面的查询返回1~5条记录。(所有最大用户1个相同。每个最大用户5个不同)

更新 获取每个最大类别的用户ID

这个怎么样?这没有
分组依据
,只需要1次完整扫描

    SELECT
        IF(cat1wins >= @mxc1, @mxu1 := login_id, @mxu1) AS userid1,
        IF(cat1wins >= @mxc1, @mxc1 := cat1wins, @mxc1) AS max_cat1wins,

        IF(cat2wins >= @mxc2, @mxu2 := login_id, @mxu2) AS userid2,
        IF(cat2wins >= @mxc2, @mxc2 := cat2wins, @mxc2) AS max_cat2wins,

        IF(cat3wins >= @mxc3, @mxu3 := login_id, @mxu3) AS userid3,
        IF(cat3wins >= @mxc3, @mxc3 := cat3wins, @mxc3) AS max_cat3wins,

        IF(cat4wins >= @mxc4, @mxu4 := login_id, @mxu4) AS userid4,
        IF(cat4wins >= @mxc4, @mxc4 := cat4wins, @mxc4) AS max_cat4wins,

        IF(cat5wins >= @mxc5, @mxu5 := login_id, @mxu5) AS userid5,
        IF(cat5wins >= @mxc5, @mxc5 := cat5wins, @mxc5) AS max_cat5wins
    FROM stats, (
        SELECT
          @mxc1 := 0, @mxc2 := 0, @mxc3 := 0, @mxc4 := 0, @mxc5 := 0,
          @mxu1 := 0, @mxu2 := 0, @mxu3 := 0, @mxu4 := 0, @mxu5 := 0
    ) x;
最后,我们使用join with login table获取登录信息

请注意,下面的查询返回1~5条记录。(所有最大用户1个相同。每个最大用户5个不同)



你要找的是一个
联盟
谢谢你的编辑,我的意思是5比1。我的坏:)你要找的是一个
联盟
谢谢你的编辑,我的意思是5比1。My bad:)您可以使用PHP为loop@scrowler当然,但在DB上创建单个查询通常被认为是最好的方法,@scrowler是的。对不起,我想我没有正确阅读你的评论。当然,查询可以构建在循环中。UNION运算符有可能消除重复的行,而UNION ALL运算符不会删除重复的行。如果需要区分cat1wins行和cat2wins2行,则可以在每个查询的选择列表中包含一个文本。(不能保证这些行将按照产生每一行的查询的顺序返回,甚至不能保证每个查询都会产生一行。)@ChemBlob9999:不是这样,但您可以
(选择'Cat1'作为Wins,stats.login_id,…LIMIT 1)UNION ALL(选择'Cat2',…)
,然后,您可以使用该列来标识哪一行是哪一行。您可以使用PHP为loop@scrowler当然,但在DB上创建单个查询通常被认为是最好的方法,@scrowler是的。对不起,我想我没有正确阅读你的评论。当然,查询可以构建在循环中。UNION运算符有可能消除重复的行,而UNION ALL运算符不会删除重复的行。如果需要区分cat1wins行和cat2wins2行,则可以在每个查询的选择列表中包含一个文本。(不能保证这些行将按照产生每一行的查询的顺序返回,甚至不能保证每个查询都会产生一行。)@ChemBlob9999:不是这样,但您可以
(选择'Cat1'作为Wins,stats.login_id,…LIMIT 1)UNION ALL(选择'Cat2',…)
,然后你就可以用这个列来识别哪一行是哪一行。谢谢你的回答…这个图库的这一部分实际上每个类别只能放一张用户照片。在实施任何解决方案之前,我将研究此方法。我编辑了结果集,以返回第一个类别,其中用户是赢家。感谢您的回答……实际上,图库的这一部分每个类别只能容纳一张用户照片。在实现任何解决方案之前,我将研究此方法。我编辑了结果集,以返回用户是赢家的第一个类别。这将给他多行(每个用户一行)。我认为他在为每个统计寻找顶级用户。这将给他多行(每个用户一行)。我认为他在寻找每个统计数据的顶级用户。