Running slow with intersect - sql

Trying to optimize a query it is updaing the records in table A based on the INTERSECT on two data sets.
UPDATE #TableA
SET IsFlag = CASE WHEN ISNULL(RJobFlag, 0) > 0 THEN 0 ELSE 1 END
FROM #TableA AS ABC
OUTER APPLY (
SELECT 1 RJobFlag
WHERE EXISTS (
SELECT ABC.COLUMN1,ABC.COLUMN2,ABC.COLUMN3,ABC.COLUMN4,ABC.COLUMN5,ABC.COLUMN6,ABC.COLUMN7,ABC.COLUMN8,ABC.COLUMN8,ABC.COLUMN9,ABC.COLUMN10,StudentID,SubjectID
INTERSECT
SELECT XYZ.COLUMN1,XYZ.COLUMN2,XYZ.COLUMN3,XYZ.COLUMN4,XYZ.COLUMN5,XYZ.COLUMN6,XYZ.COLUMN7,XYZ.COLUMN8,XYZ.COLUMN8,XYZ.COLUMN9,XYZ.COLUMN10,StudentID,SubjectID
FROM #TableB AS XYZ
WHERE XYZ.COLUMN1 = (SELECT DISTINCT ID FROM #TableC MNOP WHERE MNOP.StudentID = ABC.StudentID)
AND StudentID = ABC.StudentID
AND SubjectID = ABC.SubjectID )
) Subquery
WHERE ABC.COLUMN1= '2'
Appretiated if you have some ideas to better optimize it.
Thanks

This might be worse never know.
UPDATE tA
SET IsFlag = COALESCE(RJobFlag, 0)
FROM #TableA tA
LEFT JOIN ( SELECT 1 RJobFlag, *
FROM #TableB tB
WHERE EXISTS ( SELECT *
FROM #TableC tC
WHERE tC.ID = tB.COLUMN1 AND tC.StudentID = tB.StudentID)
) tB
ON tA.StudentID = tB.StudentID
AND tA.SubjectID = tB.SubjectID
AND tA.COLUMN1 = tB.COLUMN1
AND tA.COLUMN2 = tB.COLUMN2
AND tA.COLUMN3 = tB.COLUMN3
AND tA.COLUMN4 = tB.COLUMN4
AND tA.COLUMN5 = tB.COLUMN5
AND tA.COLUMN6 = tB.COLUMN6
AND tA.COLUMN7 = tB.COLUMN7
AND tA.COLUMN8 = tB.COLUMN8
AND tA.COLUMN9 = tB.COLUMN9
AND tA.COLUMN10 = tB.COLUMN10
If #TableA has a bunch of records and you're using outer apply or outer join every time you update it will be slow since it has to update every single record. maybe there's a way to only update the records that have changed?

Related

Multiple Joins less cost way

Below query has 3 tables where I have to do 2 joins to get a column information, It is very slow, is there any effective way to run this query?
SELECT DISTINCT
st.status_c1
FROM
schemaname.tablea st
INNER JOIN (
SELECT
lic.SpecId AS applicationid,
lic.comData AS combusappid,
lic.ageId,
lic.licId,
lic.licid,
lic.appid,
com.nybe_bustbl_id AS busid
FROM
schemaname.tableb lic
INNER JOIN tablec com ON lic.comData = com.comData
WHERE
lic.ageId = '12'
) rt ON
st.ageId = rt.ageId
AND
st.licId = rt.licId
AND
st.licid = rt.licid
AND
st.appid = rt.appid
WHERE
status_id = 3;
Your current query will create extra rows when the JOIN condition is met for multiple entries in either table and then DISTINCT will filter these duplicates out. You could try to cut down the amount of work filtering duplicates by using EXISTS:
SELECT DISTINCT
st.status_c1
FROM schemaname.tablea st
WHERE status_id = 3
AND EXISTS (
SELECT 1
FROM schemaname.tableb lic
WHERE lic.ageId = '12'
AND st.ageId = lic.ageId
AND st.licId = lic.licId
AND st.appid = lic.appid
AND EXISTS(
SELECT 1 FROM tablec com WHERE lic.comData = com.comData
)
);
There is a bunch of redundancy in the query (licid is in the SELECT and ON twice) and you don't need to use subqueries for this. I think this will work:
SELECT DISTINCT st.status_c1
FROM tablea st
INNER JOIN tableb lic ON st.ageId = lic.ageId
AND st.licId = lic.licId
AND st.appid = lic.appid
INNER JOIN tablec com ON lic.comData = com.comData
WHERE status_id = 3
and lic.ageId = '12'
How frequently are you going to run this query, how much time is it taking now and what is the explectation. Are statistcs run on all tha tables.
There are many things which we can think of, but to start with if possible could you plese give ue the like the table structure and explain plan of the query.
Also may be an index on status_c1 table tablea help. As pointed out try removing the join condition which is twice AND st.licid = rt.licid
SELECT DISTINCT st.status_c1
FROM schemaname.tablea st
INNER JOIN (
SELECT
lic.SpecId AS applicationid, lic.comData AS combusappid, lic.ageId, lic.licId, lic.licid,
lic.appid, com.nybe_bustbl_id AS busid
FROM schemaname.tableb lic
INNER JOIN tablec com ON lic.comData = com.comData
WHERE lic.ageId = '12'
) rt ON st.ageId = rt.ageId AND st.licId = rt.licId AND st.licid = rt.licid AND st.appid = rt.appid
WHERE status_id = 3;

Update a specific row with data from another table

I am using MS SQL. I want to update a specific row within a table with data from another table. I have created a query that will get the specific row I want to update. Please note that I have used a select query to select the specific row that needs to be updated. Also note that there is a sub query used to get the right row. For me, this makes it difficult to incorporate into a set statement.
select tbl1.assessmentcode, tbl1.Overview from subjectassessmentareas tbl1
inner join
(
select assessmentcode,MIN(areaseq) as minassessarea from subjectassessmentareas
where resultgroup = 'PR_Yr8_2' and ResultType = 'KUS_5'
group by AssessmentCode
) tbl2
on tbl1.AssessmentCode = tbl2.AssessmentCode and tbl1.AreaSeq = tbl2.minassessarea
where fileyear = 2016 and filesemester = 3
This gives me
Now I want to update the overview column with data from another table. This select query gives me the info I want to use to update the other table.
SELECT AssessmentCode, Overview
FROM SubjectAssessments
WHERE (ClassCampus = 'S')
and (FileYear = 2015)
and (FileSemester = 3)
and filetype = 'A'
and AssessmentCode like '08%'
This gives me
Can someone please help me with the syntax to update the overview column from the row obtained in the first query above with the overview column contained in the second query where the Query1.AssessmentCode = Query2.AssessmentCode from both queries.
How can I use a set statement but then use the first query above to say which row to set? Other similar questions just use a simple set and then a field without any where statements.
Just join these two in an updateable CTE:
;with x as (
select tbl1.assessmentcode, tbl1.Overview
from subjectassessmentareas tbl1
inner join
(
select assessmentcode,MIN(areaseq) as minassessarea from subjectassessmentareas
where resultgroup = 'PR_Yr8_2' and ResultType = 'KUS_5'
group by AssessmentCode
) tbl2
on tbl1.AssessmentCode = tbl2.AssessmentCode and tbl1.AreaSeq = tbl2.minassessarea
where fileyear = 2016 and filesemester = 3
),
y as (
SELECT AssessmentCode, Overview
FROM SubjectAssessments
WHERE (ClassCampus = 'S')
and (FileYear = 2015)
and (FileSemester = 3)
and filetype = 'A'
and AssessmentCode like '08%'
),
z as (
select x.Overview as dest, y.Overview as src
from x join y on x.AssessmentCode = y.AssessmentCode
)
update z set dest = src
Try following:
;WITH cteBaseInfo AS
(
SELECT AssessmentCode, Overview
FROM SubjectAssessments
WHERE (ClassCampus = 'S')
and (FileYear = 2015)
and (FileSemester = 3)
and filetype = 'A'
and AssessmentCode like '08%'
)
, cteToBeUpdated AS
(
select tbl1.assessmentcode, tbl1.Overview from subjectassessmentareas tbl1
inner join
(
select assessmentcode,MIN(areaseq) as minassessarea from subjectassessmentareas
where resultgroup = 'PR_Yr8_2' and ResultType = 'KUS_5'
group by AssessmentCode
) tbl2
on tbl1.AssessmentCode = tbl2.AssessmentCode and tbl1.AreaSeq = tbl2.minassessarea
where fileyear = 2016 and filesemester = 3.
)
UPDATE subjectassessmentareas
SET Overview = (SELECT Overview FROM cteBaseInfo WHERE AssessmentCode = subjectassessmentareas.AssessmentCode)
WHERE AssessmentCode IN (SELECT AssessmentCode FROM cteToBeUpdated)
Please note that, here AssessmentCode should be Primary Key.

Getting the Rows in Table 1 That does not Match Table 2 Using JOIN on Multiple Columns

Hi I have the Query Like this :
SELECT TT2.whs_code,
TT2.pdt_code,
TT2.fresh_frozen_status,
TT2.case_dt_yyyymmdd,
TT2.qty_cases,
TT2.qty_wt
FROM #TempTable2 AS TT2
LEFT OUTER JOIN #TempTable AS TT1
ON TT1.whs_code = TT2.whs_code
AND TT1.pdt_code = TT2.pdt_code
AND TT1.fresh_frozen_status = TT2.fresh_frozen_status
AND TT1.case_dt_yyyymmdd = TT2.case_dt_yyyymmdd
The Thing is I want to select the columns in #TempTable2 That are not existed in #TempTable1 based on
whs_code, pdt_code, fresh_frozen_status, case_dt_yyyymmdd
means that lets say a set of data
1,115G,FR,20160222 is in #TempTable1 So If a set of data Say
1,115G,FR,20160223 has to be selected or
1,115G,FZ,20160223 has to be selected or
2,115G,FR,20160223 has to be selected
but not 1,115G,FR,20160222
I would use NOT EXISTS.
SELECT TT2.whs_code,
TT2.pdt_code,
TT2.fresh_frozen_status,
TT2.case_dt_yyyymmdd,
TT2.qty_cases,
TT2.qty_wt
FROM #TempTable2 AS TT2
WHERE NOT EXISTS (
SELECT TOP 1 *
FROM #TempTable AS TT1
WHERE tt1.whs_code = tt2.whs_code
AND tt1.pdt_code = tt2.pdt_code
AND TT1.fresh_frozen_status = tt2.fresh_frozen_status
AND TT1.case_dt_yyyymmdd = TT2.case_dt_yyyymmdd
)

Link tables based on column value

Is it possible to pull values from 2 different tables based on the value of a column? For example, I have a table with a boolean column that either returns 0 or 1 depending on what the end user selects in our program. 0 means that I should pull in the default values. 1 means to use the user's data.
If my table Table1 looked like this:
Case ID Boolean
====================
1 0
2 1
3 1
4 0
5 0
Then I would need to pull Case IDs 1,4,and 5's corresponding data from table Default and Case IDs 3 and 4's corresponding data from table UserDef. Then I would have to take these values, combine them, and reorder them by Case ID so I can preserve the order in the resulting table.
I am fairly inexperienced with SQL but I am trying to learn. Any help or suggestions are greatly appreciated. Thank you in advance for your help.
Something like this:
SELECT
t1.CaseID
,CASE WHEN t1.Boolean = 1 THEN dt.Col1 ELSE ut.Col1 END AS Col1
,CASE WHEN t1.Boolean = 1 THEN dt.Col2 ELSE ut.Col2 END AS Col2
FROM Table1 t1
LEFT JOIN DefaultTable dt ON dt.CaseID = t1.CaseID
LEFT JOIN UserDefTable ut ON ut.CaseID = t1.CaseID
ORDER BY t1.CaseID
You join on both tables and then use CASE in SELECT to choose from which one to display data.
Option B:
WITH CTE_Combo AS
(
SELECT 0 as Boolean, * FROM Default --replace * with needed columns
UNION ALL
SELECT 1 AS Boolean, * FROM UserDef --replace * with needed columns
)
SELECT * FROM Table1 t
LEFT JOIN CTE_Combo c ON t.CaseID = c.CaseID AND t.Boolean = c.Boolean
ORDER BY t.CaseID
This might be even simpler - using CTE make a union of both tables adding artificial column, and then join CTE and your Table using both ID and flag column.
SELECT t1.CaseID,
ISNULL(td.data, tu.data) userData -- pick data from table_default
-- if not null else from table_user
FROM table1 t1
LEFT JOIN table_default td ON t1.CaseID = td.CaseID -- left join with table_default
AND t1.Boolean = 0 -- when boolean = 0
LEFT JOIN table_user tu ON t1.CaseID = tu.CaseID -- left join with table_user
AND t1.Boolean = 1 -- when boolean = 1
ORDER BY t1.CaseID

select records that don't have certain values in 2 columns

I need to select some rows that don't have certain values in 2 columns. Currently I am doing this for a single column by doing the following:
SELECT *
FROM MyTable
WHERE (ManufacturerID = #ManufacturerID)
AND ItemID NOT IN(
SELECT ItemID FROM UpdateMyTable WHERE ManufacturerID=#ManufacturerID
)
But now I need to filter out rows that don't contain 2 column values at the same time: ItemID and ChildItemID
How would I accomplish this?
SELECT
*
FROM
MyTable AS data
LEFT JOIN
(SELECT x, y, z FROM UpdateMyTable) AS check
ON data.x = check.x
AND data.y = check.y
AND data.z = check.z
WHERE
x = #x
AND check.x IS NULL
OR
SELECT
*
FROM
MyTable AS data
WHERE
x = #x
AND NOT EXISTS (
SELECT
*
FROM
UpdateMyTable AS check
WHERE
data.x = check.x
AND data.y = check.y
AND data.z = check.z
)
You could use a JOIN instead of a NOT IN.
SELECT *
FROM MyTable t
INNER JOIN UpdateMyTable u ON t.ManufacturerId = u.ManufacturerId
WHERE t.ManufacturerId = #ManufacturerId
AND t.ItemId != u.ItemId
AND t.ItemId != u.ChildItemId