Performance tuning of this query? - sql

I have below query to support employee pagination sorted by employee name
SELECT rowNumAlias
,Employee.employeeId
,Employee.NAME
FROM (
SELECT row_number() OVER (
ORDER BY Employee.NAME ASC
) rowNumAlias
,employeeId
,NAME
FROM Employee
) employeeData
INNER JOIN Employee ON Employee.employeeId = employeeData.employeeId
WHERE rowNumAlias BETWEEN ? AND ?
Where parameter rowNumAlias can be any integer number between 1 and 100
This query is taking around 7 seconds on my sql server database having 1 million records. Is there a way i can minimize query execution time ?

You can try like this:
SELECT * FROM (
SELECT (SELECT row_number() OVER (ORDER BY e2.NAME ASC) FROM Employee e2 WHERE Employee.employeeId = E2.employeeId) rowNumAlias,
,Employee.employeeId
,Employee.NAME
FROM Employee
) e3 WHERE e3.rowNumAlias BETWEEN ? AND ?

You can try to use CTE for this.
;WITH employeeData as
(
SELECT row_number() OVER (ORDER BY Employee.NAME ASC) rowNumAlias,
employeeId,
NAME
FROM Employee
)
SELECT employeeData.rowNumAlias,
employeeData.employeeId,
employeeData.NAME
FROM employeeData
INNER JOIN Employee ON Employee.employeeId = employeeData.employeeId
WHERE rowNumAlias BETWEEN ? AND ?

If you are on SQL Server 2012+ you can use the ORDER BY ... OFFSET ... FETCH ...syntax to do pagination:
SELECT EmployeeId, Name
FROM Employee
ORDER BY Employee.Name ASC OFFSET ? ROWS FETCH NEXT ? ROWS ONLY
OFFSET specifies how many rows to skip and FETCH NEXT how many to get. See the documentation.
In earlier versions you should be able to get better performance by using a common table expression (with proper indexes this query looks like it executes in halt the time of your original according to my execution plan):
;With cte (rownum, employeeid, name) as (
SELECT
rownum = row_number() OVER (ORDER BY employee.name ASC),
employeeid,
name
FROM employee
)
SELECT rownum, employeeid, name
FROM cte
WHERE rownum BETWEEN ? AND ?;

Related

How to run SQL Server CTE more than once?

I am running a CTE Query as given below
WITH CTE AS(
SELECT EmpId, EmpName, RN = ROW_NUMBER()OVER(PARTITION BY EmpId ORDER BY EmpId)
FROM Employeetemp
)
SELECT * FROM CTE
DELETE FROM CTE WHERE RN > 1
But I am getting issues in it as I can run either Select Query or Delete Query.
My second question is "What is CTE" ? Is it an object, view or anything else.
Thanks a lot in advance.
You cannot do this in SQL Server with a single query. Instead, one method to do what you want uses a temporary table:
SELECT EmpId, EmpName,
RN = ROW_NUMBER()OVER(PARTITION BY EmpId ORDER BY EmpId)
INTO #EmployeeTemp
FROM Employeetemp;
SELECT * FROM Employeetemp;
DELETE FROM Employeetemp
WHERE EmpId IN (SELECT EmpId FROM #Employeetemp WHERE RN > 1);

need query syntax to fetch latest by PKID after joining multiple tables

I have 3 tables:
select * from company
select * from emp_profile
select * from emp_salary_upgrade_tracker
table 1, company_pkid, company_code, company_name
table 2, emp_profile_pkid,company_fk_id, emp_number, emp_name, salary
table 3, salary_pk_id,emp_profile_fk_id,emp_number, old_salary, current salary
whenever an employee's salary is changed, its tracked in emp_salary_upgrade_tracker.
I need to write a query to fetch
company_code, emp_number, emp_name, old_salary, current salary
Here the result should have the latest entry ,ie latest salary change from emp_salary_upgrade_tracker.
After joining the tables, i need to fetch the latest from emp_salary_upgrade_tracker(order by pkid may be).
But am clueless of the query syntax. Please help
Use a subquery to get lates ids:
select c.company_code,
e.emp_number,
e.emp_name,
t.old_salary,
t.current_salary
from(select emp_profile_fk_id, max(salary_pk_id) as salary_pk_id
from emp_salary_upgrade_tracker group by emp_profile_fk_id) m
join emp_salary_upgrade_tracker t on m.salary_pk_id = t.salary_pk_id
join emp_profile e on t.emp_profile_fk_id = e.emp_profile_pk_id
join company c on e.company_fk_id = c.company_pkid
Here's a way using row_number to select the row containing the latest value in the emp_salary_upgrade_tracker table when ordered by its primary key.
select * from (
select *,
row_number() over (partition by esut.emp_number order by esut.salary_pk_id desc) rn
from emp_salary_upgrade_tracker esut
join emp_profile ep on ep.emp_profile_pk_id = esut.emp_profile_fk_id
join company c on c.company_pk_id = ep.company_fk_id
) t where rn = 1

query without duplicates SQL

I have query with duplicates. And now I need to build query without duplicates. I'm trying to do it, but my query need long time. My query with duplicates:
SELECT
c.*
FROM
Clients c
INNER JOIN
(
SELECT
iin,
COUNT(iin) AS countIIN
FROM
Clients
GROUP BY
iin
HAVING
COUNT(iin) > 1
) cc
ON c.IIN = cc.IIN
ORDER BY
c.last_name DESC
I need above anti-query.
You can use below query to find only unique record.
WITH CTE AS
(SELECT *, COUNT(IIN) OVER (PARTITION BY IIN) RECORDCOUNT FROM CLIENTS)
SELECT * FROM CTE WHERE RECORDCOUNT =1
make sure * should be replace in query with required column.
Also if you want to fetch unique record from duplicate list as well then you can choose below query
WITH CTE AS
(SELECT *, RECORD_NUMBER() OVER (PARTITION BY IIN ORDER BY IIN) RECORDCOUNT FROM CLIENTS)
SELECT * FROM CTE WHERE RECORDCOUNT =1
To find duplicates in SQL Row_Number() function is best option,
Please check following query
WITH [CTE NoDuplicates] AS
(
SELECT
RN = ROW_NUMBER() OVER (PARTITION BY iin ORDER BY c.last_name DESC),
*
FROM Clients
)
DELETE FROM [CTE DUPLICATE] WHERE RN = 1

How to select a row based on its row number?

I'm working on a small project in which I'll need to select a record from a temporary table based on the actual row number of the record.
How can I select a record based on its row number?
A couple of the other answers touched on the problem, but this might explain. There really isn't an order implied in SQL (set theory). So to refer to the "fifth row" requires you to introduce the concept
Select *
From
(
Select
Row_Number() Over (Order By SomeField) As RowNum
, *
From TheTable
) t2
Where RowNum = 5
In the subquery, a row number is "created" by defining the order you expect. Now the outer query is able to pull the fifth entry out of that ordered set.
Technically SQL Rows do not have "RowNumbers" in their tables. Some implementations (Oracle, I think) provide one of their own, but that's not standard and SQL Server/T-SQL does not. You can add one to the table (sort of) with an IDENTITY column.
Or you can add one (for real) in a query with the ROW_NUMBER() function, but unless you specify your own unique ORDER for the rows, the ROW_NUMBERS will be assigned non-deterministically.
What you're looking for is the row_number() function, as Kaf mentioned in the comments.
Here is an example:
WITH MyCte AS
(
SELECT employee_id,
RowNum = row_number() OVER ( order by employee_id )
FROM V_EMPLOYEE
ORDER BY Employee_ID
)
SELECT employee_id
FROM MyCte
WHERE RowNum > 0
There are 3 ways of doing this.
Suppose u have an employee table with the columns as emp_id, emp_name, salary. You need the top 10 employees who has highest salary.
Using row_number() analytic function
Select * from
( select emp_id,emp_name,row_number() over (order by salary desc) rank
from employee)
where rank<=10
Using rank() analytic function
Select * from
( select emp_id,emp_name,rank() over (order by salary desc) rank
from employee)
where rank<=10
Using rownum
select * from
(select * from employee order by salary desc)
where rownum<=10;
This will give you the rows of the table without being re-ordered by some set of values:
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT '1')) AS RowID, * FROM #table
If using SQL Server 2012 you can now use offset/fetch:
declare #rowIndexToFetch int
set #rowIndexToFetch = 0
select
*
from
dbo.EntityA ea
order by
ea.Id
offset #rowIndexToFetch rows
fetch next 1 rows only

Sql query to fetch 3rd lowest value

I have a table called employee_salary, having two columns(emp_id, emp_salary) in it.
I have a requirement to fetch 3rd lowest emp_salary from this table. In this case, what should be my query so that i can get the exact value.
I have tested this in Postgres Database. I hope this query work in all type of database. please try this.
SELECT
[emp_salary]
FROM [employee_salary]
GROUP BY [emp_salary]
ORDER BY [emp_salary] LIMIT 1 OFFSET 2;
This may be one solution
select top 1 * from
(
select top 3 * from
(
select distinct emp_sal from employee order by asc emp_sal
) d orderby desc emp_sal
)
SELECT TOP 1 * FROM employee_salary WHERE emp_salary in (SELECT TOP 3 emp_salary FROM employee_salary ORDER BY emp_salary) ORDER BY emp_salary DESC
However, this does not work in all DBs. You need to find out alternative. For eg. in Informix, the statement will be SELECT FIRST 1 *
Using windowing functions... this construct is for SQL Server:
;WITH CTE AS
(
SELECT ..., ROW_NUMBER() OVER (ORDER BY emp_salary) AS rn
FROM myTable
)
SELECT ...
FROM CTE
WHERE rn = 3
for identical salaries you can get using RANK () function in SQL Server
;WITH CTE AS
(
SELECT ..., RANK() OVER (ORDER BY emp_salary) AS rn
FROM myTable
)
SELECT ...
FROM CTE
WHERE rn = 3
I got the answer by executing the following query in sql server 2008
Select MIN(emp_salary) from MyTable Where emp_salary in
(Select DISTINCT TOP 3 emp_salary from MyTable order by 1 DESC)
I got the 3rd minimum value.
DISTINCT is used to when one or more salary are same.
select * from table_name where col_name = (select (min(col_name) from table_name where col_name > (select min(col_name) from table_name where col_name > (select min(col_name) from table_name)));
You need 3rd lowest Salary. Let dive deep in the question.
1st requirement is Need Salary , 2nd requirement is need lowest salary and 3rd requirement is 3rd Lowest Salary
SELECT * FROM employee_salary // "It will give us Salary"
ORDER BY emp_salary DESC //"It will show lowest salary on top"
LIMIT 2,1 // As wee need 3rd salary , i am saying LIMIT 2,1 skip first 2 and show 3rd one