将 SQL COUNT(*) 与 INNER JOIN 查询组合

问题描述 投票:0回答:2

我做了一个查询来计算一个表的每一行并对其进行排名,但我无法将查询加入一个表中。

我一直在尝试制作一个排行榜,并且我已经设法根据他们拥有的点数(即第一、第二、第三等)对每一行进行排名。由于我的 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分

我已经创建的代码显然能够做到这一点。

如何合并这些查询,以便它们可以一起打印?

mysql count inner-join
2个回答
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'
        ); 
}

diagram


0
投票

如果您将此过程分为两个阶段,其中第一阶段是生成一个

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)
© www.soinside.com 2019 - 2024. All rights reserved.