如何使用单个 SQL 聚合函数查询为同一个聚合函数获取多个结果?

Posted

技术标签:

【中文标题】如何使用单个 SQL 聚合函数查询为同一个聚合函数获取多个结果?【英文标题】:How to get multiple results for the same aggregate function using a single SQL aggregate function query? 【发布时间】:2021-08-31 22:56:42 【问题描述】:

我是 SQL 新手,我一直在尝试为我的数据库创建视图。 当我介绍聚合函数时,我很快就发现了这个问题;

所以在我的数据库中有两个表: 用户/员工数据表和组(例如“会计”、“支持”等)。

我想使用查询/视图为该组中的员工返回每个组的整个员工条目以及(该组的)最低/最高工资。

这是表格:

--- 员工数据---

CREATE TABLE `db_java-sql-hookup`.`tbl_employee-data` (
    `ID_Employee` bigint UNIQUE NOT NULL AUTO_INCREMENT,
    `fk_IDGroup` tinyint,
    `EmployeeName` varchar(30) UNIQUE NOT NULL,
    `Email` varchar(255) NOT NULL,
    `Password` varchar(255) NOT NULL,
    `Salary` int,
    PRIMARY KEY (`ID_Employee`),
    FOREIGN KEY (`fk_IDGroup`) REFERENCES `db_java-sql-hookup`.`tbl_groups`(`pk_IDGroup`)
);

INSERT INTO `db_java-sql-hookup`.`tbl_employee-data` (`EmployeeName`, `Email`, `Password`)
VALUES
("TestA", "TestA@web.com", "1234"),
("TestB", "TestB@web.com", "1234"),
("TestC", "TestC@web.com", "abcde"),
("TestD", "TestD@web.com", "0000"),
("TestE", "TestE@web.com", "g8t3");
### Set Groups ###
UPDATE `db_java-sql-hookup`.`tbl_employee-data`
    SET `fk_IDGroup` = 1 WHERE `tbl_employee-data`.`ID_Employee` = 1; 
UPDATE `db_java-sql-hookup`.`tbl_employee-data`
    SET `fk_IDGroup` = 1 WHERE `tbl_employee-data`.`ID_Employee` = 2;
UPDATE `db_java-sql-hookup`.`tbl_employee-data`
    SET `fk_IDGroup` = 1 WHERE `tbl_employee-data`.`ID_Employee` = 3;
UPDATE `db_java-sql-hookup`.`tbl_employee-data`
    SET `fk_IDGroup` = 2 WHERE `tbl_employee-data`.`ID_Employee` = 4;
UPDATE `db_java-sql-hookup`.`tbl_employee-data`
    SET `fk_IDGroup` = 2 WHERE `tbl_employee-data`.`ID_Employee` = 5;
### Set Salaries ###
UPDATE `db_java-sql-hookup`.`tbl_employee-data`
    SET `Salary` = 1000 WHERE `tbl_employee-data`.`ID_Employee` = 1; 
UPDATE `db_java-sql-hookup`.`tbl_employee-data`
    SET `Salary` = 500 WHERE `tbl_employee-data`.`ID_Employee` = 2;
UPDATE `db_java-sql-hookup`.`tbl_employee-data`
    SET `Salary` = 2000 WHERE `tbl_employee-data`.`ID_Employee` = 3;
UPDATE `db_java-sql-hookup`.`tbl_employee-data`
    SET `Salary` = 750 WHERE `tbl_employee-data`.`ID_Employee` = 4;
UPDATE `db_java-sql-hookup`.`tbl_employee-data`
    SET `Salary` = 300 WHERE `tbl_employee-data`.`ID_Employee` = 5;

---分组数据---

CREATE TABLE `db_java-sql-hookup`.`tbl_groups` (
    `pk_IDGroup` tinyint UNIQUE NOT NULL AUTO_INCREMENT,
    `GroupName` varchar(40) NOT NULL,
    PRIMARY KEY (`pk_IDGroup`)
);

INSERT INTO `db_java-sql-hookup`.`tbl_groups` (`GroupName`)
VALUES 
    ("Accounting"),
    ("Support"),
    ("Development"),
    ("Test"); 

之前,我处理过这些视图(我想将它们结合起来):

### MaxSalaryEmp ###    
DROP VIEW IF EXISTS `db_java-sql-hookup`.`view_MaxSalaryEmployee`;
CREATE VIEW `db_java-sql-hookup`.`view_MaxSalaryEmployee` AS    
    SELECT `ID_Employee`, `EmployeeName`, `Salary`
    FROM `db_java-sql-hookup`.`tbl_employee-data`
    WHERE `Salary` = 
        (SELECT MAX(`Salary`) FROM `db_java-sql-hookup`.`tbl_employee-data`);

### Avg,Min,Max Group Salary ###
DROP VIEW IF EXISTS `db_java-sql-hookup`.`view_CombinedGroupSalary`;
CREATE VIEW `db_java-sql-hookup`.`view_CombinedGroupSalary` AS   
    SELECT `GroupName`, 
        AVG(`Salary`) AS `AvgSalary`,
        MIN(`Salary`) AS `MinSalary`,
        MAX(`Salary`) AS `MaxSalary`
    FROM `db_java-sql-hookup`.`tbl_groups` AS grp
    LEFT JOIN `db_java-sql-hookup`.`tbl_employee-data` AS emp
    ON grp.`pk_IDGroup` = emp.`fk_IDGroup`
    GROUP BY `GroupName`
    ORDER BY `GroupName`;

我尝试过这样的事情:

SELECT `GroupName`, `ID_Employee`, `EmployeeName`,  `Salary`,
    MAX(`Salary`) AS `MaxSalary`
FROM `db_java-sql-hookup`.`tbl_groups` AS grp
LEFT JOIN `db_java-sql-hookup`.`tbl_employee-data` AS emp
ON grp.`pk_IDGroup` = emp.`fk_IDGroup`
GROUP BY `GroupName`
ORDER BY `GroupName`;

我希望最终结果如下所示: https://i.stack.imgur.com/xsmLT.png

(除了,它应该派出合适的员工而不是这里发生的任何事情)

提前谢谢你!

【问题讨论】:

【参考方案1】:

我不清楚你想要完成什么。 您只想要每个组的***员工还是想要按组列出所有员工并显示每个组的最高薪水?

如果您希望每组一个条目,请使用您的组合工资视图,如下所示:

SELECT grp.`GroupName`, emp.`ID_Employee`, emp.`EmployeeName`,  emp.`Salary`,
   grp.`MaxSalary` 
FROM  `db_java-sql-hookup`.`view_CombinedGroupSalary` grp
LEFT JOIN `db_java-sql-hookup`.`tbl_employee-data` AS emp
ON grp.`pk_IDGroup` = emp.`fk_IDGroup` and grp.`MaxSalary` = emp.`Salary`
ORDER BY `GroupName`;

如果您需要列出所有员工,请执行以下操作:

SELECT grp.`GroupName`, emp.`ID_Employee`, emp.`EmployeeName`,  emp.`Salary`,
   cs.`MaxSalary`
FROM `db_java-sql-hookup`.`tbl_groups grp`
INNER JOIN `db_java-sql-hookup`.`view_CombinedGroupSalary cs 
on grp.`pk_IDGroup` = cs.`pk_IDGroup`
LEFT JOIN `db_java-sql-hookup`.`tbl_employee_data` AS emp
ON grp.`pk_IDGroup` = emp.`fk_IDGroup`
ORDER BY grp.`GroupName`, emp.`EmployeeName`;

要使这些查询起作用,您需要在组合工资视图中包含 pk_IDGroup 列:

DROP VIEW IF EXISTS `db_java-sql-hookup`.`view_CombinedGroupSalary`;
CREATE VIEW `db_java-sql-hookup`.`view_CombinedGroupSalary` AS   
    SELECT `pk_IDGroup`,
        `GroupName`, 
        AVG(`Salary`) AS `AvgSalary`,
        MIN(`Salary`) AS `MinSalary`,
        MAX(`Salary`) AS `MaxSalary`
    FROM `db_java-sql-hookup`.`tbl_groups` AS grp
    LEFT JOIN `db_java-sql-hookup`.`tbl_employee-data` AS emp
    ON grp.`pk_IDGroup` = emp.`fk_IDGroup`
    GROUP BY `pk_IDGroup`,`GroupName`
    ORDER BY `GroupName`;

【讨论】:

非常感谢!第一个查询实际上正是我想要的。我不知道我也可以加入视图。【参考方案2】:

对于这个问题,我认为你不需要使用 group by,而是需要使用“user-defined-variables”:

这个link 可以告诉你如何在 mysql 中按分区获取最大值(在 mssql 中它的工作方式不同)。

这是我需要删除“db_java-sql-hookup”的 sql 小提琴中的问题 (sqlfiddle) 的解决方案。从表格中,您可以使用以下代码:

select `GroupName`, `ID_Employee`, `EmployeeName`,  `Salary`,
       @max:=IF(@custtype!=`GroupName`,`Salary`,@max),
       @custtype:=`GroupName`
FROM (
  select `GroupName`, `ID_Employee`, `EmployeeName`,  `Salary`
  FROM `db_java-sql-hookup`.`tbl_groups` AS grp
  LEFT JOIN `db_java-sql-hookup`.`tbl_employee-data` AS emp
  ON grp.`pk_IDGroup` = emp.`fk_IDGroup`
  order by `GroupName`, `Salary` desc
) a, (select @max:=0, @custtype:='') t

如果您需要有关其工作原理的更多详细信息,请告诉我,我会添加它。

【讨论】:

以上是关于如何使用单个 SQL 聚合函数查询为同一个聚合函数获取多个结果?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server聚合函数

如何在单个查询中使用联接和聚合函数更新表中的多行

SqlServer聚合函数

SQL语句汇总——聚合函数分组子查询及组合查询

SQL Server聚合函数与聚合开窗函数

在 sql 查询中使用聚合函数时避免 group by 子句