如何简化这个子查询?
Posted
技术标签:
【中文标题】如何简化这个子查询?【英文标题】:How to simplify this subquery? 【发布时间】:2015-02-04 08:56:16 【问题描述】:我从http://www.programmerinterview.com/index.php/database-sql/derived-table-vs-subquery/ 看到了这个子查询,它以下面的子查询为例,但说它可以写得更简单。谁能告诉我该怎么做?谢谢!
一个名为employee 的表,其中包含employee_name、last_name、employee_salary 和employee_number 列。我们希望找到所有薪水高于平均水平的员工。
select employee_name
from employee
where employee_salary >
(select avg(employee_salary)
from employee)
【问题讨论】:
对我来说似乎很简单。 我猜;他们指的是SELF JOIN;详细说明@programmerinterview.com/index.php/database-sql/… 【参考方案1】:试试这个:
SELECT employee_name
FROM employee e
INNER JOIN (SELECT AVG(employee_salary) salary FROM employee) e1 ON e.employee_salary > e1.salary;
或
SELECT employee_name
FROM employee e
WHERE EXISTS (SELECT 1 FROM employee e1 WHERE e.employee_salary > AVG(e1.employee_salary));
【讨论】:
【参考方案2】:我认为您的查询设计得很好。 使用 JOIN 效率会降低,并且 HAVING 子句将在检索后过滤数据。您将获取所有员工,然后过滤平均工资。
【讨论】:
【参考方案3】:希望这会有所帮助
--DECLARE A TABLE VARIABLE
DECLARE @Emp AS TABLE
(
ID INT
,EMPLOYEE_NAME VARCHAR(50)
,EMPLOYEE_SALARY NUMERIC(18,2)
)
-- ADD SOME VALUES TO THE TABLE
INSERT INTO @Emp
VALUES (1,'DANNY',7000),(2,'JOHN',10000),(3,'DAVID',1000)
--AVERAGE SALARY IS 6000..
--USING COMMON TABLE EXPRESSIONS
; WITH CTE AS
(
SELECT
AVG(EMPLOYEE_SALARY) AS AVGSALARY
FROM @EMP
)
SELECT
EMPLOYEE_NAME
FROM
@Emp EMPLOYEE -- MY TABLE
INNER JOIN
CTE
ON
EMPLOYEE_SALARY>CTE.AVGSALARY
【讨论】:
【参考方案4】:您可以使用OVER 子句计算average
的薪水以及当前员工的薪水是否大于它。很遗憾,window
函数不能在 where 子句中使用,所以你也应该使用命令表表达式。
DECLARE @employee TABLE
(
[employee_name] VARCHAR(12)
,[employee_salary] INT
)
INSERT INTO @employee ([employee_name], [employee_salary])
VALUES ('Empl1', 100)
,('Empl2', 200)
,('Empl3', 300)
,('Empl4', 400)
,('Empl5', 500)
,('Empl6', 600)
,('Empl7', 700)
,('Empl8', 800)
-- your query
select employee_name
from @employee
where employee_salary >
(select avg(employee_salary)
from @employee)
-- alternative query
;WITH DataSource AS
(
select employee_name
,employee_salary - AVG(employee_salary) OVER () AS diff
from @employee
)
SELECT employee_name
FROM DataSource
WHERE diff > 0
【讨论】:
有趣的方法,但是针对 300,000 行的表测试这两个查询,原始查询的执行比使用 OVER 的查询要好约 5.5 倍(相对于批处理的成本为 15% 与 85%)。 【参考方案5】:为sql server 2012
select iif(((employee_salary) > (SELECT avg(employee_salary) FROM employee)),
employee_name ,null) employee_name
FROM employee
group by employee_name,employee_salary
【讨论】:
这个查询甚至无法编译。以上是关于如何简化这个子查询?的主要内容,如果未能解决你的问题,请参考以下文章