简体   繁体   中英

How to simplify this subquery?

I saw this subquery from http://www.programmerinterview.com/index.php/database-sql/derived-table-vs-subquery/ and it has this following subquery as example, but says it could be written much more simply. Could anyone tell me how to do that? Thank you!

A table called employee with columns employee_name, last_name, employee_salary, and employee_number. We want to find all employees who have a salary that is above average.

   select employee_name 
    from employee
    where employee_salary >
    (select avg(employee_salary)
            from employee)

You can use OVER clause to calculate the average salary and if the current employee's salary is bigger than it. Unfortunatelly, window functions can not be used in where clause, so you should use comman table expression, too.

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

Try this:

SELECT employee_name 
FROM employee e 
INNER JOIN (SELECT AVG(employee_salary) salary FROM employee) e1 ON e.employee_salary > e1.salary;

OR

SELECT employee_name 
FROM employee e 
WHERE EXISTS (SELECT 1 FROM employee e1 WHERE e.employee_salary > AVG(e1.employee_salary)); 

I think your query is well designed. Using JOIN will be less efficient and HAVING clause will filter data after retrieve. You will get all employees then filter on average salary.

Hope this will help

--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

for 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 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM