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

时间:2014-01-24 01:39:22

标签: php mysql sql mysqli

我有一个"领导者"在我的网站上,DESC LIMIT 1选择了5个不同类别的顶级用户;在统计信息和登录表之间使用5个单独的INNER JOIN生成库,但所有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)

$result1 = mysqli_query($con,$cat1wins);
WHILE ($Category1Wins = mysqli_fetch_assoc($result1)) {
$Cat1User = $Category1Wins['user'];
$Cat1Statement = $Category1Wins['statement'];
echo "code"; //etc
}

我想必须有更好的方法来做到这一点;我想我可以这样开始:

$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";

然后在$ catAllwins中的每个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 (显示一个示例)

对数组进行排序
$SortedCat1WinsArray = natsort($Cat1WinsArray);

然后按降序添加 array_reverse

$DescSortedCat1WinsArray = array_reverse($SortedCat1WinsArray);

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

3 个答案:

答案 0 :(得分:2)

您可以将各个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 */

答案 1 :(得分:2)

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

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;

与原始的五个查询相比,这样做有两个重要的区别。首先,如果有人在两个或更多类别中排名第一,那么他们只会在这里出现一次。其次,如果多个人在一个类别中并列最佳,那么所有人都包括在内。

答案 2 :(得分:0)

更新

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

这个怎么样?这没有GROUP BY,只需要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;

最后我们使用登录表

获取登录信息

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

SELECT
    y.*, login.login_id, login.user, login.picture, login.statement,
    IF(y.userid1 = login.login_id, max_cat1wins, NULL) AS max1,
    IF(y.userid2 = login.login_id, max_cat2wins, NULL) AS max2,
    IF(y.userid3 = login.login_id, max_cat3wins, NULL) AS max3,
    IF(y.userid4 = login.login_id, max_cat4wins, NULL) AS max4,
    IF(y.userid5 = login.login_id, max_cat5wins, NULL) AS max5
FROM 
(
    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
) y INNER JOIN login
WHERE login.login_id IN (userid1, userid2, userid3, userid4, userid5);