繁体   English   中英

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

[英]Possible to reduce number of queries from 5 to 1?

我的网站上有一个“领导者”画廊,其中 5 个不同类别的顶级用户由 DESC LIMIT 1 选出; 图库是在 stats 和 login 表之间使用 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'] 等)。 这听起来有道理吗? 我将不胜感激任何反馈! 有更容易的方法吗?

您可以将单独的 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;

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

更新

获取每个最大类别的用户 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;

最后我们使用 join with login table 来获取登录信息

请注意,以下查询返回 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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM