Query is very slow - sql-server

I have tables
table1
epid etid id EValue reqdate
----------- ----------- ----------- ------------ ----------
15 1 1 498925307069 2012-01-01
185 1 2 A5973FC43CE3 2012-04-04
186 1 2 44C6A4B776A2 2012-04-05
205 1 2 7A0ED3F1DA13 2012-09-19
206 1 2 77771D65F9C4 2012-09-19
207 1 2 AD74A4AA41BD 2012-09-19
208 1 2 9595ABE5A0C8 2012-09-19
209 1 2 7611D2FB395B 2012-09-19
210 1 2 04A510D6067A 2012-09-19
211 1 2 24D43EC268F8 2012-09-19
table2
PEId Id EPId
----------- ----------- -----------
43 9 15
44 10 15
45 11 15
46 12 15
47 13 15
48 14 15
49 15 15
50 16 15
51 17 15
52 18 15
table3
PLId PEId Id ToPayId
----------- ----------- ----------- -----------
71 43 9 1
72 43 9 2
73 44 10 1
74 44 10 2
75 45 11 1
76 45 11 2
77 46 12 1
78 46 12 2
79 47 13 1
80 47 13 2
I want to get one id whose count is less than 8 in table 3 and order by peid in table 2,
I have written query
SELECT Top 1 ToPayId FROM
(
SELECT Count(pl.ToPayId) C, pl.ToPayId
FROM table3 pl
INNER JOIN table2 pe ON pl.peid = pe.peid
INNER JOIN table1 e ON pe.epid = e.epid
WHERE e.EtId=1 GROUP BY pl.ToPayId
) As T
INNER JOIN table2 p ON T.ToPayId= p.Id
WHERE C < 8 ORDER BY p.PEId ASC
This query executes more than 1000 times in stored procedure depends on the entries in user-defined-table-type using while condition.
But it is very slow as we have millions of entries in each table.
Can anyone suggest better query regarding above?

maybe try with the having clause to get rid of the from select
select table2.id as due
from table3 inner join table2 on table2.PEId=table3.PEId...
group by ...
having count(due) <8
order by ...
-> you have a redundant Id column in table3 : seems pretty useless as the couple PEId and Id appears unique so remove it and reduce the size of table 3 by 25% hence improving performance of db

Will.. since you did not provide enough sample data and I am not sure what exactly your business logic is. So that I can just modify the code in blind.
SELECT ToPayId
FROM (
SELECT TOP 1 Count(pl.ToPayId) C, pl.ToPayId, pe.PEId
FROM table3 as pl
INNER JOIN table2 as pe ON pl.peid = pe.peid AND pl.ToPayId = pe.Id
INNER JOIN table1 e ON pe.epid = e.epid
WHERE e.EtId=1
GROUP BY pl.ToPayId, pe.PEId
HAVING Count(pl.ToPayId) < 8
ORDER BY pe.PEId ASC
) AS T

Related

SQL - Select non repeating columns

I have a table like
id name R_id mgr_id
----------------------------
61 a 22 1
62 a 22 2
62 b 23 1
63 c 24 4
63 b 22 3
64 c 25 3
and I would like to get the following result set
R_id mgr_id
--------------
22 1
23 1
24 4
25 3
I would like select repeating R_ids only once
I tried using this query but with not much success, can anyone help me.
SELECT DISTINCT R_id, mgr_id from DT
Perhaps something like this... WITH TIES clause in concert with Row_NUmber()
Example
Select Top 1 with ties
R_ID
,mgr_id
From #YourTable
Order By Row_Number() over (Partition By R_ID order by Mgr_id)
Returns
R_ID mgr_id
22 1
23 1
24 4
25 3

In SQL is there a way to simulate SAS MERGE operation

Lets say I have the following 2 datasets:
A B C
----------- ----------- -----------
1 100 1000
1 120 1001
2 140 1002
2 160 1003
3 180 1004
3 190 1005
3 200 1006
and
A D E
----------- ----------- -----------
1 61 2000
1 62 2001
1 63 2001
2 64 2002
3 65 2004
3 66 2005
3 67 2006
3 68 2006
Is it possible to generate the following output dataset (. represents null)?
A B C D E
----------- ----------- ----------- ----------- -----------
1 100 1000 61 2000
1 120 1001 62 2001
1 . . 63 2001
2 140 1002 64 2002
2 160 1003 . .
3 180 1004 65 2004
3 190 1005 66 2005
3 200 1006 67 2006
3 . . 68 2006
The merge takes all the records from both tables, and adds them to the result set at most once.
If records join they are not multiplied as in a classical sql join. Each record is aligned with a matching record and when they run out of records null is inserted.
I've been thinking that perhaps the new partitioning functions can achieve this, but I've been away from SQL too long now and I cant think of a way to do this "special join".
I've also considered making a distinct list of the keys and then left joining them to the 2 tables, but then I get stuck, because the join will still multiply the record counts..
You can do this with the row_number() windowing function. Naming the two datasets DS1 and DS2 the result will look like this:
WITH DS1Seq As (
SELECT A, B, C, row_number() OVER (partition by A order by A, B, C) As SeqNumber
FROM DS1
),
DS2Seq As (
SELECT A, D, E, row_number() OVER (partition by A order by A, D, E) As SeqNumber
FROM DS2
)
SELECT coalesce(DS1Seq.A, DS2Seq.A) As A, B, C, D, E
FROM DS1Seq
FULL JOIN DS2Seq on DS1Seq.A = DS2Seq.A AND DS1Seq.SeqNumber = DS2Seq.SeqNumber

Database Multiple Table Join Queries

I really don't know what queries to be combined using these table to achieve my coressponding output please assist me
Table 1
w_ref t_id q_id qty
110 111 500 1
111 112 500 2
112 113 500 3
Table 2
t_id q_id material-x material-y material_id
111 500 14 15 7
112 500 18 18 7
113 500 10 11 8
Table 3
id material_name
7 abc
8 def
I expect that joining table output like this
Output
w_ref qty material-x material-y material_name
110 1 14 15 abc
111 2 18 07 abc
112 3 10 11 def
Here is a simple example of a SQL of a INNER JOIN. This will give you a basic understanding from the results given.
SELECT a.w_ref, a.t_id, a.q_id, a.qty, b.material-x FROM table1 a INNER JOIN table2 b ON b.t_id = a.t_id;
However their is very little of what you're trying to achieve and should not just post a question asking someone to sort it. Maybe add what you have tried so far and what outcomes you have had.

SQL Rank does not work as expected

Im trying to use SQL function Rank() to get a list the top records of several groups. Here is what im tring that does not work :
select hc.hId, hc.DpId, hc.Rank
from (
select d.hId, DpId, Rank()
OVER (Partition by DpId ORDER BY d.hId) AS Rank
FROM CurDp d
INNER JOIN HostList h on d.DpId = h.hId
INNER JOIN Coll_hList pch on d.hId = pch.hId
where h.Model = 'PRIMARY'
) hc where hc.Rank <= 10
I get the top 10 records as follows :
HId | DpId | Rank
-------x------x------
7 | 590 | 1
18 | 590 | 2
23 | 590 | 3
24 | 590 | 4
26 | 590 | 5
36 | 590 | 6
63 | 590 | 7
80 | 590 | 8
84 | 590 | 9
88 | 590 | 10
But when I use CROSS APPLY, which the function I need because i have to get that kind of records on different models, I use this code :
select pch.hId, cc.DpId, cc.Rank from from Coll_hList pch
cross apply
(
select hc.hId, hc.DpId, hc.Rank
from (
select d.hId, DpId, Rank()
OVER (Partition by DpId ORDER BY d.hId) AS Rank
FROM CurrDp d
INNER JOIN HostList h on d.DpId = h.hId
where h.Model = 'PRIMARY' and d.hId = pch.hId
) hc where hc.Rank <= 10
) cc
Here, I get always rank 1, and it doesn't filter anything (not showing the whole result) :
HId | DpId | Rank
-------x------x------
7 590 1
18 590 1
23 590 1
24 590 1
26 590 1
36 590 1
63 590 1
80 590 1
84 590 1
88 590 1
124 590 1
125 590 1
133 590 1
Am I doing it wrong ? Is it because of CROSS APPLY ?
I also used dense_rank() instead of rank(), but it shows the same result.
Any help to achieve this request with CROSS APPLY would be greatly appreciated.
Thanks
In the first case, you join on Coll_hList and get a result set of more than 10 entries which then are ranked.
In the second case, in your apply-sub-select, you only create a one-entry result set. Ranking of that results in rank one.
Your ranking has to be done in the outer statement:
select pch.hId, cc.DpId, Rank()
OVER (Partition by cc.DpId ORDER BY cc.hId) AS Rank
from Coll_hList pch
cross apply
(
select d.hId, DpId
FROM CurrDp d
INNER JOIN HostList h on d.DpId = h.hId
where h.Model = 'PRIMARY' and d.hId = pch.hId
) cc

SQL Server : Update a column

I have a TableA
ID MatCh01 Match02 Status
1 1001 12
2 1001 12
3 1001 12
4 1002 44
5 1002 47
6 1003 22
7 1003 22
8 1004 55
9 1004 57
I want to populate column = status with "FAIL" when :
For same match01, there exist different match02. Expected TableA :
ID MatCh01 Match02 Status
1 1001 12 NULL
2 1001 12 NULL
3 1001 12 NULL
4 1002 44 FAIL
5 1002 47 FAIL
6 1003 22 NULL
7 1003 22 NULL
8 1004 55 FAIL
9 1004 57 FAIL
Please NOTE: FAIL all 'match01' if its corresponding 'match02' is different.
Thanks
Basically this says Update all Values in TableA when the MAX and MIN of Column Match02 are not equal (meaning match01 has multiple rows with different values for match 02).
UPDATE A
SET Status = 'FAIL'
FROM TableA A
INNER JOIN (SELECT
a2.Match01
FROM TableA A2
GROUP BY a2.Match01
HAVING MAX(Match02) <> MIN(Match02)) B ON
A.Match01 = B.Match01
When there's more than one distinct value of match02 for any match01, update those rows with the same match01.
UPDATE t1
SET Status = 'FAIL'
FROM TableA t1
WHERE t1.Match01 in
(
SELECT t2.Match01
FROM TableA t2
GROUP BY t2.Match01
HAVING COUNT(DISTINCT t2.Match02) > 1
)

Resources