[英]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.