我做了一个查询来计算一个表的每一行并对其进行排名,但我无法将查询加入一个表中。
我一直在尝试制作一个排行榜,并且我已经设法根据他们拥有的点数(即第一、第二、第三等)对每一行进行排名。由于我的 SQL 版本,我不得不使用 ROW_NUMBER() 的解决方法,我正在努力将该查询包含在我已经得到的这个 INNER JOIN 查询中。
INNER JOIN查询:
$query = mysqli_query($conn, "SELECT students.username,
CONCAT(spoints.points, 'pts') AS pointspts,
CONCAT(students.firstname, ' ', students.lastname) AS name,
CASE WHEN sex = 'M' THEN 'Male' ELSE 'Female' END AS sexes,
students.house,
CONCAT(students.age, 'yrs') AS ageyrs
FROM students
INNER JOIN spoints ON students.username=spoints.username
ORDER BY points DESC");
我试图合并到
COUNT(*)
查询中的 INNER JOIN
查询:
$rank = mysqli_query($conn, "SELECT username, 1 + ( SELECT count(*) FROM spoints a WHERE a.points > b.points ) AS rank
FROM spoints b
ORDER BY rank;");
我正在尝试将它们联系起来,以便它们形成一个简洁的表格,这就是问题所在。
我尝试了多种代码加入它们,例如:
$query = mysqli_query($conn, "SELECT students.username,
CONCAT(spoints.points, 'pts') AS pointspts,
CONCAT(students.firstname, ' ', students.lastname) AS name,
CASE WHEN sex = 'M' THEN 'Male' ELSE 'Female' END AS sexes,
students.house, CONCAT(students.age, 'yrs') AS ageyrs,
(SELECT 1 + (SELECT count(*) FROM spoints a WHERE a.points > b.points ) AS rank FROM spoints b) AS rank
FROM students
INNER JOIN spoints ON students.username=spoints.username
ORDER BY points DESC");
但这似乎只返回一个空白列或
"mysqli_query(): (21000/1242): Subquery returns more than 1 row"
错误。
我也尝试过将查询与两个
mysqli_fetch_arrays
合并,但后来我遇到了这个相互排斥的问题,其中只有 $rank query
或 $query query
的第一列会打印出来。即
while ($roow = mysqli_fetch_array($rank)){
while ($row = mysqli_fetch_array($query)){
printf("
<tr>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
</tr>", $roow['rank'], $row['name'], $row['ageyrs'], $row['sexes'], $row['house'], $row['pointspts']
);
}
}
退货:
站立 | 姓名 | 年龄 | 性别 | 房子 | 积分 |
---|---|---|---|---|---|
第一 | 高根意大利面 | 17岁 | 男 | 塔斯曼 | 234点 |
第一 | 阿米·贝克勒 | 12岁 | 女 | 太平洋 | 24分 |
第一 | 简舒特 | 18岁 | 男 | 珊瑚 | 0分 |
或
while ($row = mysqli_fetch_array($query)){
while ($roow = mysqli_fetch_array($rank)){
printf("
<tr>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
</tr>", $roow['rank'], $row['name'], $row['ageyrs'], $row['sexes'], $row['house'], $row['pointspts']
);
}
}
退货:
站立 | 姓名 | 年龄 | 性别 | 房子 | 积分 |
---|---|---|---|---|---|
第一 | 高根意大利面 | 17岁 | 男 | 塔斯曼 | 234点 |
第二 | 高根意大利面 | 17岁 | 男 | 塔斯曼 | 234点 |
第三 | 高根意大利面 | 17岁 | 男 | 塔斯曼 | 234点 |
我希望我的代码返回这个:
站立 | 姓名 | 年龄 | 性别 | 房子 | 积分 |
---|---|---|---|---|---|
第一 | 高根意大利面 | 17岁 | 男 | 塔斯曼 | 234点 |
第二 | 阿米·贝克勒 | 12岁 | 女 | 太平洋 | 24分 |
第三 | 简舒特 | 18岁 | 男 | 珊瑚 | 0分 |
我已经创建的代码显然能够做到这一点。
如何合并这些查询,以便它们可以一起打印?
这是我认为这是获取预期数据的更好方法的示例,希望对您有所帮助。
更详细地编辑以便更好地理解。
select concat( s.firstname , ' ', s.lastname) as name,
concat(s.age,'yrs') as Age ,
CASE WHEN s.sex = 'M' THEN 'Male' ELSE 'Female' END AS Sex
,s.house as House
# use sum(p.points) to count the number of points,
# or count(p.points) if there is one # point per line
,sum(p.points) as points
# Use the points table as the main one
# and include the link with the left join of the students table
from spoints p
# I see that your secondary key link is by username,
# in my case I used p.student_id = s.id
# but in your case use
# p.username = s.username
left join students s on p.student_id = s.id
# perform the grouping with reference to the username for your case
# group by p.username
group by p.student_id
# para obter os melhor colocados
# utilize 'order by' para deixalos no top com ordenação 'desc'
order by points desc
# if your version has support use limit 3 to get only the first 3
limit 3
结果
姓名 | 年龄 | 性别 | 房子 | 积分 |
---|---|---|---|---|
阿米·贝克勒 | 12岁 | 女 | 太平洋 | 151 |
高根意大利面 | 17岁 | 男 | 塔斯曼 | 141 |
简舒特 | 18岁 | 男 | 珊瑚 | 54 |
示例数据库
CREATE DATABASE teste;
use teste
create table students
(
id int auto_increment
primary key,
username text null,
firstname text null,
lastname text null,
age int null,
house text null,
sex text null,
constraint students_id_uindex
unique (id)
);
INSERT INTO teste.students (username, firstname, lastname, age, house, sex) VALUES ('kogan.spaghetti', 'Kogan', 'Spaghetti', 17, 'Tasman ', 'M')
INSERT INTO teste.students (username, firstname, lastname, age, house, sex) VALUES ('ami.beckler', 'Ami', 'Beckler', 12, 'Pacific ', 'F')
INSERT INTO teste.students (username, firstname, lastname, age, house, sex) VALUES ('jan.schuette ', 'Jan', 'Schuette', 18, 'Coral ', 'M')
INSERT INTO teste.students (username, firstname, lastname, age, house, sex) VALUES ('px.t1', 'px', 't1', 16, 'Pacific ', 'M')
INSERT INTO teste.students (username, firstname, lastname, age, house, sex) VALUES ('px.t2', 'px', 't2', 17, 'Pacific ', 'F')
INSERT INTO teste.students (username, firstname, lastname, age, house, sex) VALUES ('px.t3', 'px', 't3', 18, 'Pacific ', 'M')
INSERT INTO teste.students (username, firstname, lastname, age, house, sex) VALUES ('cx.t4', 'cx', 't4', 15, 'Coral ', 'M')
INSERT INTO teste.students (username, firstname, lastname, age, house, sex) VALUES ('cx.t5', 'cx', 't5', 14, 'Coral ', 'D')
INSERT INTO teste.students (username, firstname, lastname, age, house, sex) VALUES ('cx.t6', 'cx', 't6', 13, 'Coral ', 'M')
INSERT INTO teste.students (username, firstname, lastname, age, house, sex) VALUES ('tx.t7', 'tx', 't7', 13, 'Tasman ', 'M')
INSERT INTO teste.students (username, firstname, lastname, age, house, sex) VALUES ('tx.t8', 'tx', 't8', 13, 'Tasman ', 'M')
INSERT INTO teste.students (username, firstname, lastname, age, house, sex) VALUES ('tx.t9', 'tx', 't9', 13, 'Tasman ', 'M')
create table spoints
(
id int auto_increment
primary key,
username text null,
points int null,
student_id int null,
constraint spoints_id_uindex
unique (id),
constraint spoints_students_id_fk
foreign key (student_id) references students (id)
);
INSERT INTO teste.spoints (username, points, student_id) VALUES ('jan.schuette ', 2, 3)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('jan.schuette ', 5, 3)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('jan.schuette ', 2, 3)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('jan.schuette ', 9, 3)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('jan.schuette ', 6, 3)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('jan.schuette ', 6, 3)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('jan.schuette ', 1, 3)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('jan.schuette ', 3, 3)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('jan.schuette ', 8, 3)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('jan.schuette ', 7, 3)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('jan.schuette ', 2, 3)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('jan.schuette ', 3, 3)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('ami.beckler', 3, 2)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('ami.beckler', 12, 2)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('ami.beckler', 34, 2)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('ami.beckler', 5, 2)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('ami.beckler', 3, 2)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('ami.beckler', 6, 2)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('ami.beckler', 77, 2)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('ami.beckler', 8, 2)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('ami.beckler', 2, 2)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('ami.beckler', 1, 2)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('kogan.spaghetti', 1, 1)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('kogan.spaghetti', 1, 1)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('kogan.spaghetti', 5, 1)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('kogan.spaghetti', 4, 1)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('kogan.spaghetti', 1, 1)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('kogan.spaghetti', 75, 1)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('kogan.spaghetti', 7, 1)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('kogan.spaghetti', 1, 1)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('kogan.spaghetti', 6, 1)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('kogan.spaghetti', 34, 1)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('kogan.spaghetti', 1, 1)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('kogan.spaghetti', 5, 1)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('px.t1', 2, 4)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('px.t2', 2, 5)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('px.t3', 2, 6)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('cx.t4', 2, 7)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('cx.t5', 2, 8)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('cx.t6', 2, 9)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('tx.t7', 2, 10)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('tx.t8', 2, 11)
INSERT INTO teste.spoints (username, points, student_id) VALUES ('tx.t9', 2, 12)
php 例子
$i=0;
while ($row = mysqli_fetch_assoc($query)) {
$i++;
/*
use filter to add the st, nd, rd complement
using the variable $i as a line counter knowing that your query is already sorted
*/
$filter = array('th','st','nd','rd','th','th','th','th','th','th');
if (($i %100) >= 11 && ($i%100) <= 13)
$rank = $i. 'th';
else
$rank = ($i)? $i. $filter[$i % 10] : $i;
printf("
<tr>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
</tr>",$rank, $row['name'], $row['Age'], $row['Sex'], $row['House'], $row['points'].'pts'
);
}
如果您将此过程分为两个阶段,其中第一阶段是生成一个
view
的数据来解释分数的增加,那么第二阶段可以使用该 view
然后执行排名计算。
从@Rafa Akito 的回答中稍微借用表模式(稍微修改)-即:
CREATE TABLE `tbl_students` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`username` TEXT NULL,
`firstname` TEXT NULL,
`lastname` TEXT NULL,
`age` INT(11) NULL DEFAULT NULL,
`house` TEXT NULL,
`sex` TEXT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `students_id_uindex` (`id`)
)
ENGINE=InnoDB;
CREATE TABLE `tbl_scores` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`username` TEXT NULL,
`points` INT(11) NULL DEFAULT NULL,
`student_id` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `scores_id_uindex` (`id`),
INDEX `scores_students_id_fk` (`student_id`),
CONSTRAINT `scores_students_id_fk` FOREIGN KEY (`student_id`) REFERENCES `tbl_students` (`id`)
)
ENGINE=InnoDB;
INSERT INTO `tbl_scores` (`id`, `username`, `points`, `student_id`) VALUES
(1, 'jan.schuette', 2, 3),
(2, 'jan.schuette', 5, 3),
(3, 'jan.schuette', 2, 3),
(4, 'jan.schuette', 9, 3),
(5, 'jan.schuette', 6, 3),
(6, 'jan.schuette', 6, 3),
(7, 'jan.schuette', 1, 3),
(8, 'jan.schuette', 3, 3),
(9, 'jan.schuette', 8, 3),
(10, 'jan.schuette', 7, 3),
(11, 'jan.schuette', 2, 3),
(12, 'jan.schuette', 3, 3),
(13, 'ami.beckler', 3, 2),
(14, 'ami.beckler', 12, 2),
(15, 'ami.beckler', 34, 2),
(16, 'ami.beckler', 5, 2),
(17, 'ami.beckler', 3, 2),
(18, 'ami.beckler', 6, 2),
(19, 'ami.beckler', 77, 2),
(20, 'ami.beckler', 8, 2),
(21, 'ami.beckler', 2, 2),
(22, 'ami.beckler', 1, 2),
(23, 'kogan.spaghetti', 1, 1),
(24, 'kogan.spaghetti', 1, 1),
(25, 'kogan.spaghetti', 5, 1),
(26, 'kogan.spaghetti', 4, 1),
(27, 'kogan.spaghetti', 1, 1),
(28, 'kogan.spaghetti', 75, 1),
(29, 'kogan.spaghetti', 7, 1),
(30, 'kogan.spaghetti', 1, 1),
(31, 'kogan.spaghetti', 6, 1),
(32, 'kogan.spaghetti', 34, 1),
(33, 'kogan.spaghetti', 1, 1),
(34, 'kogan.spaghetti', 5, 1),
(35, 'px.t1', 2, 4),
(36, 'px.t2', 2, 5),
(37, 'px.t3', 2, 6),
(38, 'cx.t4', 2, 7),
(39, 'cx.t5', 2, 8),
(40, 'cx.t6', 2, 9),
(41, 'tx.t7', 2, 10),
(42, 'tx.t8', 2, 11),
(43, 'tx.t9', 2, 12);
INSERT INTO `tbl_students` (`id`, `username`, `firstname`, `lastname`, `age`, `house`, `sex`) VALUES
(1, 'kogan.spaghetti', 'Kogan', 'Spaghetti', 17, 'Tasman ', 'M'),
(2, 'ami.beckler', 'Ami', 'Beckler', 12, 'Pacific ', 'F'),
(3, 'jan.schuette', 'Jan', 'Schuette', 18, 'Coral ', 'M'),
(4, 'px.t1', 'px', 't1', 16, 'Pacific ', 'M'),
(5, 'px.t2', 'px', 't2', 17, 'Pacific ', 'F'),
(6, 'px.t3', 'px', 't3', 18, 'Pacific ', 'M'),
(7, 'cx.t4', 'cx', 't4', 15, 'Coral ', 'M'),
(8, 'cx.t5', 'cx', 't5', 14, 'Coral ', 'D'),
(9, 'cx.t6', 'cx', 't6', 13, 'Coral ', 'M'),
(10, 'tx.t7', 'tx', 't7', 13, 'Tasman ', 'M'),
(11, 'tx.t8', 'tx', 't8', 13, 'Tasman ', 'M'),
(12, 'tx.t9', 'tx', 't9', 13, 'Tasman ', 'M');
然后创建
view
:
create view vw_stud_rank as
select
st.`username`,
sum( sc.`points` ) as `score`
from tbl_students st
join tbl_scores sc on sc.`student_id`=st.`id`
group by st.`id`;
最后是排名计算查询:
select
s.*,
case
when @pr = `score` then @cr
when @pr := `score` then @cr := @cr + 1
end as `rank`
from `vw_stud_rank` s,
( select @cr:=0,@pr:=null ) x
order by `score` desc;
上面的查询然后产生:
+-----------------+-------+------+
| username | score | rank |
+-----------------+-------+------+
| ami.beckler | 151 | 1 |
| kogan.spaghetti | 141 | 2 |
| jan.schuette | 54 | 3 |
| px.t1 | 2 | 4 |
| px.t2 | 2 | 4 |
| px.t3 | 2 | 4 |
| cx.t4 | 2 | 4 |
| cx.t5 | 2 | 4 |
| cx.t6 | 2 | 4 |
| tx.t7 | 2 | 4 |
| tx.t8 | 2 | 4 |
| tx.t9 | 2 | 4 |
+-----------------+-------+------+
12 rows in set (0.02 sec)
如果你把它和你自己的功能结合起来(在这里)——即:
DELIMITER $$
CREATE FUNCTION ordinal(number BIGINT)
RETURNS VARCHAR(64)
DETERMINISTIC
BEGIN
DECLARE ord VARCHAR(64);
SET ord = (SELECT CONCAT(number, CASE
WHEN number%100 BETWEEN 11 AND 13 THEN "th"
WHEN number%10 = 1 THEN "st"
WHEN number%10 = 2 THEN "nd"
WHEN number%10 = 3 THEN "rd"
ELSE "th"
END));
RETURN ord;
END$$
DELIMITER ;
然后您可以将上面的查询修改为:
select
s.*,
case
when @pr = `score` then ordinal(@cr)
when @pr := `score` then @cr := ordinal(@cr + 1)
end as `rank`
from `vw_stud_rank` s,
( select @cr:=0, @pr:=null ) x
order by `score` desc;
它本身产生:
+-----------------+-------+------+
| username | score | rank |
+-----------------+-------+------+
| ami.beckler | 151 | 1st |
| kogan.spaghetti | 141 | 2nd |
| jan.schuette | 54 | 3rd |
| px.t1 | 2 | 4th |
| px.t2 | 2 | 4th |
| px.t3 | 2 | 4th |
| cx.t4 | 2 | 4th |
| cx.t5 | 2 | 4th |
| cx.t6 | 2 | 4th |
| tx.t7 | 2 | 4th |
| tx.t8 | 2 | 4th |
| tx.t9 | 2 | 4th |
+-----------------+-------+------+
12 rows in set (0.00 sec)