Performance tuning on link server table joining with CTE - sql-server

Want to tune the performance by reducing the number of SELECT on OPENQUERY by doing JOIN operation.
Here is how my query look like.
Query:
;WITH CTE AS
(
SELECT
[EmployeeFirstName], [EmployeeMiddleName],
[EmployeeLastName], [EmployeeAddress]
FROM
Employee
WHERE
[EmployeeSalary] >= 200000
)
SELECT
[First Name], [Fathers Husband Name], [Last Name], [Department Name]
FROM
OPENQUERY ([Depart], 'SELECT [First Name], [Fathers Name], [Last Name],[Department Name]
FROM Department
INNER JOIN CTE C1 ON PATINDEX(''[First Name]'',''C1.[EmployeeFirstName]'') > 0');
Error:
Invalid object name 'CTE'

Try the following
;WITH CTE AS
(
SELECT
[EmployeeFirstName], [EmployeeMiddleName],
[EmployeeLastName], [EmployeeAddress]
FROM
LocalServer.Database.Schema.Employee
WHERE
[EmployeeSalary] >= 200000
)
SELECT
[First Name], [Fathers Husband Name], [Last Name], [Department Name]
--It's better to specify the table eg: C1.ColumnName
FROM
(
SELECT [First Name], [Fathers Name], [Last Name],[Department Name]
FROM LinkedServer.Database.Schema.Department
INNER JOIN CTE C1
ON PATINDEX([First Name],C1.[EmployeeFirstName]) > 0
) TBL;

Related

sql pivot with dynamic columns

i have already posted my question in the link sql group by order by and top in a same query the result for my request is,
SELECT
[Company Name],
[Designation],
[comp id],
[Employee Name]
FROM
(
SELECT emp.[Emp ID],
comp.[Company Name],
design.[Designation],
emp.[comp id],
emp.[Employee Name],
ROW_NUMBER() OVER (PARTITION BY emp.[Comp ID], emp.[Design ID] ORDER BY emp.[Comp ID] desc, emp.[Design ID] desc, emp.[Emp ID] desc) RowNum
from employee as emp
join designation as design on design.[Design ID]=emp.[Design ID]
join company as comp on comp.[Comp ID]=emp.[Comp ID]
) a
WHERE RowNum <=2
can anyone help me to pivot this query, thanks in advance
As you have a set number of employess in your list (from your comment) you don't need it to be dynamic. A regular pivot should do the trick:
select [Company Name],Emp1,Emp2,Emp3,Emp4 from (
SELECT
[Company Name],
[Employee Name],
'Emp' + cast(ROW_NUMBER() OVER (PARTITION BY [Comp ID] ORDER BY [Design ID], [Emp ID] desc) as char(2)) as RowNum
FROM
(
SELECT emp.[Emp ID],
comp.[Company Name],
design.[Designation],
emp.[Design ID],
emp.[comp id],
emp.[Employee Name],
ROW_NUMBER() OVER (PARTITION BY emp.[Comp ID], emp.[Design ID] ORDER BY emp.[Comp ID] desc, emp.[Design ID] desc, emp.[Emp ID] desc) RowNum
from employee as emp
join designation as design on design.[Design ID]=emp.[Design ID]
join company as comp on comp.[Comp ID]=emp.[Comp ID]
) a
WHERE RowNum <=2
) as pivotdata
pivot (max([Employee Name]) for [RowNum] in (Emp1,Emp2,Emp3,Emp4)) as P

Cannot Select a Temporary table's Column?

Seems I cannot select the temporary table's column by the column name it inherits from the views I'm selecting from. I get the error: "Msg 207, Level 16, State 1, Procedure GetConsolidatedData, Line 44 [Batch Start Line 0]
Invalid column name 'comp_id'."
select *
into #tmp0
from Competitor_View
where [Competitor Name] like #competitor_name;
select *
into #tmp1
from #tmp0
where [Competitor Part Number] like #competitor_part;
select *
into #CustomerResult
from #tmp1
where [Koyo Part Number] like #koyo_part;
--------------
select *
into #tmp3
from Customer_View
where [Customer Name] like #customer_name;
select *
into #tmp4
from #tmp3
where [Customer Part Number] like #customer_part;
select *
into #CompetitorResult
from #tmp4
where [Koyo Part Number] like #koyo_part;
--everything after this fails
select
#CompetitorResult.comp_id,
#CompetitorResult.[Competitor Part Number],
#CompetitorResult.[Competitor Comment],
#CompetitorResult.[Competitor Name],
#CompetitorResult.[Koyo Part Number] as [Associated Koyo Part Number],
#CustomerResult.cust_id,
#CustomerResult.[Customer Part Number],
#CustomerResult.[Customer Comment],
#CustomerResult.[Customer Name]
from #CompetitorResult
join #CustomerResult
on #CompetitorResult.[Koyo Part Number] = #CustomerResult.[Koyo Part Number];
I know I've got the right name for the column because running the following confirms that:
SELECT *
FROM tempdb.sys.columns
WHERE object_id = OBJECT_ID('tempdb..#CompetitorResult')
Your Query should look something like this... (without any temp tables)
select cp.comp_id
,cp.[Competitor Part Number]
,cp.[Competitor Comment]
,cp.[Competitor Name]
,cp.[Koyo Part Number] as [Associated Koyo Part Number]
,cu.cust_id
,cu.[Customer Part Number]
,cu.[Customer Comment]
,cu.[Customer Name]
from Competitor_View cp
INNER JOIN Customer_View cu ON cp.[Koyo Part Number] = cu.[Koyo Part Number]
where cp.[Koyo Part Number] like #koyo_part
AND cp.[Competitor Part Number] like #competitor_part
AND cp.[Competitor Name] like #competitor_name
AND cu.[Customer Name] like #customer_name
AND cu.[Customer Part Number] like #customer_part
AND cu.[Koyo Part Number] like #koyo_part

Getting 4th row of query result

I am using Microsoft SQL Server 2012 and I have this query (below). It returns everything correctly but I cannot figure out how to get only the 4th row to return.
I know how to do it with a simple query but with a query this complex I don't know how to only return the 4th row. Since I am using MS SQL Server, I cannot use Limit/Offset. How and where should I place code to only print the 4th row? I'm stumped. Thanks.
SELECT T.[First Name],
T.[Last Name],
T.[Middle Name],
T.[Country Name],
T.[Designation Name],
Salary.Emp_Salary AS 'Current Salary'
FROM
(
SELECT
Emp_First_Name AS "First Name",
Emp_Last_Name AS "Last Name",
Emp_Middle_Name AS "Middle Name",
Country_Name AS "Country Name",
Desig_Name as "Designation Name",
MAX(Emp_Salary_Change_Year) AS "Time"
FROM Employee_Details
INNER JOIN Country ON Employee_Details.Emp_Country_Id = Country.Country_Id
INNER JOIN State ON Employee_Details.Emp_State_Id = State.State_Id
INNER JOIN Designation ON Employee_Details.Desig_Id = Designation.Desig_Id
INNER JOIN Salary ON Employee_Details.Emp_Id = Salary.Emp_Id
GROUP BY Emp_First_Name, Emp_Last_Name,
Emp_Middle_Name, Country_Name, Desig_Name) AS T
INNER JOIN Salary ON T.Time = Salary.Emp_Salary_Change_Year
ORDER BY [Current Salary];
Use a CTE with ROW_NUMBER()
;WITH Cte AS
(
SELECT Col1, Col2, ...,
ROW_NUMBER() OVER (ORDER BY ...) AS RowNum
FROM Table
)
SELECT *
FROM Cte
WHERE RowNum = 4
You can also, use the OFFSET/FETCH keyword.
SELECT *
FROM yourTable
ORDER by yourSortColumn
OFFSET 3 ROWS -- Skip Three rows.
FETCH FIRST 1 ROW ONLY;
You can use TOP this way (first you select only 4 rown and the ordering desc select 1 row)
select TOP 1 from (
SELECT TOP 4 T.[First Name],
T.[Last Name],
T.[Middle Name],
T.[Country Name],
T.[Designation Name],
Salary.Emp_Salary AS 'Current Salary'
FROM
(
SELECT
........
) AS T
INNER JOIN Salary ON T.Time = Salary.Emp_Salary_Change_Year
ORDER BY [Current Salary])
ORDER BY [Current Salary] DESC

SQL Query to Find All distinct Duplicates across 2 columns

Sale ID Group ID
JED93B53QEJYST4102 01A42QEJAXT17A7
JED93B53QEJYST4102 01A42QEJAXT17A7
JED93B53QEJYST4102 01A42QEJAXT17A7
JED93B53QEJYST4102 01A42QEJAXT17A7
JED8754AQEJEHT4119 01C49QEJPJT133E
JED8754AQEJEHT4119 01C49QEJPJT133E
JED8754AQEJEHT4119 01C49QEJPJT133E
JEDA67C1QEJEQR4A4A 03D80QEJRSR1BC5
JEDA67C1QEJEQR4A4A 03D80QEJRSR1BC5
JED46D04QEJXOR468B 040E5QEJGQR174D
JED658D9QEJIOS4F38 053BDQEJNSS11D4
JED658D9QEJIOS4F38 053BDQEJNSS11D4
JED99C53QEJNMR4973 053BDQEJNSS11D4
JED658D9QEJIOS4F38 053BDQEJNSS11D4
JED658D9QEJIOS4F38 053BDQEJNSS11D4
JED457D4QEJFGR468F 0B829QEJHJR18F5
JED457D4QEJFGR468F 0B829QEJHJR18F5
JEDA98F8QEJCZQ4F6A 0B829QEJHJR18F5
I am stuck in a dilemma wherein I am trying to write a SQL Query that will give me only those records which has duplicate group IDs but with unique Sale IDs. My Expected Output is similar to below. Is there anyway to achieve this?
JED99C53QEJNMR4973 053BDQEJNSS11D4
JED658D9QEJIOS4F38 053BDQEJNSS11D4
JED457D4QEJFGR468F 0B829QEJHJR18F5
JEDA98F8QEJCZQ4F6A 0B829QEJHJR18F5
Any help appreciated. Thanks a lot.
EDIT: Using Group By I can achieve till this:
Sale ID Group ID
JED93B53QEJYST4102 01A42QEJAXT17A7
JED8754AQEJEHT4119 01C49QEJPJT133E
JEDA67C1QEJEQR4A4A 03D80QEJRSR1BC5
JED46D04QEJXOR468B 040E5QEJGQR174D
JED658D9QEJIOS4F38 053BDQEJNSS11D4
JED99C53QEJNMR4973 053BDQEJNSS11D4
JED457D4QEJFGR468F 0B829QEJHJR18F5
JEDA98F8QEJCZQ4F6A 0B829QEJHJR18F5
EDIT FINAL: Thanks for all the responses and the finally was able to sort this out the way I wanted it. I managed to learn something new. Apologies if my question was not clear. I required it precisely that way as the table has more than a 100,000 records and I need to audit those with different SaleID for a single GroupID. The below query by Giorgos Betsos worked
SELECT t1.[Sale ID], t1.[Group ID]
FROM mytable AS t1
JOIN (
SELECT [Group ID]
FROM mytable
GROUP BY [Group ID]
HAVING COUNT(*) > 1 AND COUNT(DISTINCT [Sale ID]) > 1
) AS t2 ON t1.[Group ID] = t2.[Group ID]
Group By t1.[Group ID], t1.[Sale ID]
It seems like the required GROUP ID values can be obtained by the following query:
SELECT [Group ID]
FROM mytable
GROUP BY [Group ID]
HAVING COUNT(*) > 1 AND COUNT(DISTINCT [Sale ID]) > 1
You can use the above query as a derived to table to join back to the original table so as to get the Sale ID value as well:
SELECT t1.[Sale ID], t1.[Group ID]
FROM mytable AS t1
JOIN (
SELECT [Group ID]
FROM mytable
GROUP BY [Group ID]
HAVING COUNT(*) > 1 AND COUNT(DISTINCT [Sale ID]) > 1
) AS t2 ON t1.[Group ID] = t2.[Group ID]
Try this,
DECLARE #Table TABLE (
[Sale ID] VARCHAR(100)
,[Group ID] VARCHAR(100)
)
insert into #Table values
('JED93B53QEJYST4102','01A42QEJAXT17A7')
,('JED93B53QEJYST4102','01A42QEJAXT17A7')
,('JED93B53QEJYST4102','01A42QEJAXT17A7')
,('JED93B53QEJYST4102','01A42QEJAXT17A7')
,('JED8754AQEJEHT4119','01C49QEJPJT133E')
,('JED8754AQEJEHT4119','01C49QEJPJT133E')
,('JED8754AQEJEHT4119','01C49QEJPJT133E')
,('JEDA67C1QEJEQR4A4A','03D80QEJRSR1BC5')
,('JEDA67C1QEJEQR4A4A','03D80QEJRSR1BC5')
,('JED46D04QEJXOR468B','040E5QEJGQR174D')
,('JED658D9QEJIOS4F38','053BDQEJNSS11D4')
,('JED658D9QEJIOS4F38','053BDQEJNSS11D4')
,('JED99C53QEJNMR4973','053BDQEJNSS11D4')
,('JED658D9QEJIOS4F38','053BDQEJNSS11D4')
,('JED658D9QEJIOS4F38','053BDQEJNSS11D4')
,('JED457D4QEJFGR468F','0B829QEJHJR18F5')
,('JED457D4QEJFGR468F','0B829QEJHJR18F5')
,('JEDA98F8QEJCZQ4F6A','0B829QEJHJR18F5')
SELECT DISTINCT t1.[Sale ID]
,t1.[Group ID]
FROM #Table AS t1
JOIN (
SELECT [Group ID]
FROM #Table
GROUP BY [Group ID]
HAVING COUNT(DISTINCT [Sale ID]) > 1
) AS t2 ON t1.[Group ID] = t2.[Group ID]
write a SQL Query that will give me only those records which has duplicate group IDs but with unique Sale IDs
Here is how to do this verbatim:
SELECT t1.[Sale ID],
t1.[Group ID]
FROM yourTable t1
INNER JOIN
(
SELECT [Group ID]
FROM yourTable
GROUP BY [Group ID]
HAVING COUNT(*) > 1 AND -- duplicate group IDs
COUNT(DISTINCT [Sale ID]) = COUNT(*) -- but all sale IDs unique
) t2
ON t1.[Group ID] = t2.[Group ID]
However, your desired output seemed to suggest something more simple:
SELECT DISTINCT [Sale ID], [Group ID]
FROM yourTable
or
SELECT [Sale ID], [Group ID]
FROM yourTable
GROUP BY [Sale ID], [Group ID]

Place Data from Same Column in Different Columns in Resultset

I have a request I wasn't sure to handle. I was thinking of using PIVOT, but I wasn't sure if that would be the way to go.
I have the following Data:
EmployeeA, DepartmentB, 1/10/2010
EmployeeA, DepartmentA, 1/1/2000
EmployeeB, DepartmentC, 1/3/2011
They want output for only the employees that have been in different departments. Something that looks like this (order is important due to the dates):
EmployeeA, DepartmentA, DepartmentB
Any help is appreciated. For some reason, my mind isn't finding a good solution.
You can do this by doing a self JOIN on the table and then using a PIVOT to get the data in the format that you want:
SELECT *
FROM
(
SELECT t1.emp, t1.dept, t1.dt
FROM test t1
INNER JOIN test t2
ON t1.emp = t2.emp
AND t1.dept != t2.dept
) x
PIVOT
(
min(dt)
for dept in ([A], [B], [C], [D], [E])
) p
See SQL Fiddle with Demo
If you remove the JOIN you will get all records, but you stated you only want the records that have been in more than one department.
Here's the answer I got which I got largely based on your work. Pivot doesn't work because I don't know the categories (in this case Department) ahead of time and I can only have two of them.
Maybe there's an easier way. I didn't use a CTE, because I believe this should work for Sybase as well which I don't think supports that.
select Meta1.[Employee ID],
Meta1.Department as PreviousDepartment,
Meta2.Department as CurrentDepartment
from
(
SELECT t1.[First Name], t1.[Last Name],
t1.[Employee ID], t1.Department, t1.[Hire Date],
ROW_NUMBER() over(PARTITION by t1.[EMPLOYEE ID] order by t1.[Hire Date]) as RowNum
FROM EMPLOYEE t1
INNER JOIN EMPLOYEE t2
ON t1.[Employee ID] = t2.[Employee ID]
AND t1.Department != t2.Department
) Meta1
inner join
(
SELECT t1.[Employee ID], t1.Department, t1.[Hire Date],
ROW_NUMBER() over(PARTITION by t1.[EMPLOYEE ID] order by t1.[Hire Date]) as RowNum
FROM EMPLOYEE t1
INNER JOIN EMPLOYEE t2
ON t1.[Employee ID] = t2.[Employee ID]
AND t1.Department != t2.Department
) Meta2
on Meta1.[Employee ID]=Meta2.[Employee ID]
where Meta1.RowNum=1
and Meta2.RowNum=2

Resources