Alternative solution for below SQL Query ,TableMasterID NOT IN take so much time - sql

Need alternative solution for below SQL Query ,TableMasterID NOT IN take so much time, If i remove AND TableMasterID NOT IN
(SELECT DISTINCT c.TableMasterID
FROM ComFinalDataBS as C
WHERE C.ComFileID IN
(SELECT Number FROM fn_SplitInt(#ComFileID,','))) text from below query then getting result in 20 seconds otherwise result getting arround 4 minus.
SELECT A.SubTitleId,TableMasterID from SubTitle as A JOIN ComTableMaster as B ON a.SubTitle = b.TblName AND TableMasterID NOT IN (SELECT DISTINCT c.TableMasterID
FROM ComFinalDataBS as C
WHERE C.ComFileID IN
(SELECT Number FROM fn_SplitInt(#ComFileID,','))) AND B.TableMasterID IN
(SELECT DISTINCT d.TableMasterID
FROM ComData as D
WHERE D.ComFileID IN
(SELECT Number FROM fn_SplitInt(#ComFileID,','))) ORDER BY A.MainTitleID

SELECT A.SubTitleId ,
TableMasterID
FROM SubTitle AS A
JOIN ComTableMaster AS B ON A.SubTitle = B.TblName
WHERE NOT EXISTS ( SELECT 1
FROM ComFinalDataBS C
WHERE TableMasterID = C.TableMasterID
AND C.ComFileID IN (
SELECT Number
FROM MEFCampus..fn_SplitInt(#ComFileID, ',') ) )
AND NOT EXISTS ( SELECT 1
FROM ComData D
WHERE TableMasterID = D.TableMasterID
AND D.ComFileID IN (
SELECT Number
FROM MEFCampus..fn_SplitInt(#ComFileID,
',') ) )
AND B.IsDeleted = 0
ORDER BY MainTitleID

Have you tried storing the result from the fn_split_string() into an indexed temp-table first? It should help the Query Optimizer a lot.
SELECT DISTINCT Number
INTO #ComFileID
FROM dbo.fn_SplitInt(#ComFileID,',')
CREATE UNIQUE CLUSTERED INDEX uq0_ComFileID ON #ComFileID (Number) WITH (FILLFACTOR = 100)
SELECT A.SubTitleId,TableMasterID
FROM SubTitle as A
JOIN ComTableMaster as B
ON a.SubTitle = b.TblName
/*
AND B.TableMasterID NOT IN (SELECT DISTINCT c.TableMasterID
FROM ComFinalDataBS as C
JOIN #ComFileID CFI
ON CFI.Number = C.ComFileID )
*/
AND NOT EXISTS ( SELECT *
FROM ComFinalDataBS as C
JOIN #ComFileID CFI
ON CFI.Number = C.ComFileID
WHERE c.TableMasterID = B.TableMasterID )
/*
AND B.TableMasterID IN (SELECT DISTINCT d.TableMasterID
FROM ComData as D
JOIN #ComFileID CFI
ON CFI.Number = D.ComFileID
*/
AND EXISTS ( SELECT *
FROM ComData as D
JOIN #ComFileID CFI
ON CFI.Number = D.ComFileID
WHERE D.TableMasterID = B.TableMasterID )
ORDER BY A.MainTitleID

Related

Why is Oracle REPLACE function not working for this string?

We have a pattern we use all the time and this is usually pretty straightforward.
sortOrder IN VARCHAR2 := 'Title'
query VARCHAR2(32767) := q'[
SELECT
Columns
FROM tables
ORDER BY {sortOrder}
]';
query := REPLACE(query, '{sortOrder}', sortOrder);
But for this string it is not working:
WITH appl_List
AS
(
SELECT DISTINCT
appls.admin_phs_ORG_code || TO_CHAR(appls.serial_num, 'FM000000') AS core_proj_number,
appls.Appl_ID
FROM TABLE(:portfolioTable) appls
),
g1SupportingProjCount AS
(
SELECT
gen1grants.silverchair_id,
COUNT(DISTINCT al.Appl_ID) AS ApplCount
FROM
appl_List al
JOIN cg_cited_reference_gen1_grant gen1grants
ON al.core_proj_number = gen1grants.ic_serial_num
JOIN cg_cited_reference_gen1 gen1refs
ON gen1grants.silverchair_id = gen1refs.silverchair_id
GROUP BY gen1grants.Silverchair_id
),
g1SupportedPubCount AS
(
SELECT
gen1grants.silverchair_id,
COUNT(DISTINCT gen1refs.gen1_wos_uid) AS PubCount
FROM
appl_List al
JOIN cg_cited_reference_gen1_grant gen1grants
ON al.core_proj_number = gen1grants.ic_serial_num
JOIN cg_cited_reference_gen1 gen1refs
ON gen1grants.silverchair_id = gen1refs.silverchair_id
GROUP BY gen1grants.Silverchair_id
),
g2SupportingProjCount AS
(
SELECT
gen2grants.silverchair_id,
COUNT(DISTINCT al.Appl_ID) AS ApplCount
FROM
appl_List al
JOIN cg_cited_reference_gen2_grant gen2grants
ON al.core_proj_number = gen2grants.ic_serial_num
JOIN cg_cited_reference_gen2 gen2refs
ON gen2grants.silverchair_id = gen2refs.silverchair_id
GROUP BY gen2grants.Silverchair_id
),
g2SupportedPubCount AS
(
SELECT
gen2grants.silverchair_id,
COUNT(DISTINCT gen2refs.gen2_wos_uid) AS PubCount
FROM
appl_List al
JOIN cg_cited_reference_gen2_grant gen2grants
ON al.core_proj_number = gen2grants.ic_serial_num
JOIN cg_cited_reference_gen2 gen2refs
ON gen2grants.silverchair_id = gen2refs.silverchair_id
GROUP BY gen2grants.Silverchair_id
),
portfolio_cg_ids AS
(
SELECT DISTINCT md.silverchair_id
FROM
(
SELECT silverchair_id
FROM cg_cited_reference_gen1_grant gen1Grants
JOIN Appl_List appls
ON appls.core_proj_number = gen1Grants.ic_serial_num
UNION
SELECT silverchair_id
FROM cg_cited_reference_gen2_grant gen2Grants
JOIN Appl_List appls
ON appls.core_proj_number = gen2Grants.ic_serial_num
) grant_sc_ids
JOIN cg_metadata md
ON grant_sc_ids.silverchair_id = md.silverchair_id
)
SELECT
silverchairId,
TITLE,
PMID,
PMCID,
publication_year as year,
referenceCount1Gen,
supportingProjectCount1Gen,
supportedPublicationCount1Gen,
referenceCount2Gen,
supportingProjectCount2Gen,
supportedPublicationCount2Gen,
COUNT(1) OVER() as TotalCount
FROM
(
SELECT
md.SILVERCHAIR_ID silverchairId,
md.TITLE,
md.PMID,
md.PMCID ,
md.publication_year as year,
g1RefCounts.referenceCount1Gen as referenceCount1Gen,
g1SupportingProjCount.ApplCount as supportingProjectCount1Gen,
g1SupportedPubCount.PubCount as supportedPublicationCount1Gen,
g2RefCounts.referenceCount2Gen as referenceCount2Gen,
g2SupportingProjCount.ApplCount as supportingProjectCount2Gen,
g2SupportedPubCount.PubCount as supportedPublicationCount2Gen,
--COUNT(1) OVER() as TotalCount
FROM cg_metadata md
-- BEGIN datascope to current portfolio
JOIN portfolio_cg_ids
ON portfolio_cg_ids.silverchair_id = md.silverchair_id
-- END datascope to current portfolio
LEFT JOIN g1SupportingProjCount
ON g1SupportingProjCount.Silverchair_id = md.silverchair_id
LEFT JOIN g2SupportingProjCount
ON g2SupportingProjCount.Silverchair_id = md.silverchair_id
LEFT JOIN g1SupportedPubCount
ON g1SupportedPubCount.Silverchair_id = md.silverchair_id
LEFT JOIN g2SupportedPubCount
ON g2SupportedPubCount.Silverchair_id = md.silverchair_id
OUTER APPLY
(
Select Count(*) as referenceCount1Gen
FROM cg_cited_reference_gen1 g1Refs
WHERE g1Refs.silverchair_id = md.silverchair_id
) g1RefCounts
OUTER APPLY
(
Select Count(*) as referenceCount2Gen
FROM cg_cited_reference_gen2 g2Refs
WHERE g2Refs.silverchair_id = md.silverchair_id
) g2RefCounts
) results
ORDER BY {sortOrder}
Are there cases where some kind of special char in the string can keep this from working?
I'm kind of perplexed. I've been using this pattern for like 3 years and I've never had this not work.
What could be breaking this?
The query has 4000+ characters.
The text is probably being truncated somewhere down the line.

sql query- group by and then join

I have 2 tables as follow:
1)passenger - with passenger_id,passenger_name and passenger_city
2)flight - with flight_id,flight_name and passenger_id.
The question is:
List the passenger details with flight id, who has travelled in more than one flight.
(This function will display the passenger details with their flight id's who has travelled in more than one flight.)
I used this query:
select * from passenger_1038299
where passengerid in(select passengerid from flight_1038299
group by passengerid
having count(passengerid)>1);
but it doesnt give me flight_ids. please tell how to retrieve flight id as well.
thanks and sorry for stupid question as new to sql.
Join the flight table to get the passenger's flights
select * from passenger_1038299 p
join flight_1038299 f on f.passenger_id = p.passenger_id
where p.passengerid in(
select passengerid from flight_1038299 group by passengerid having count(passengerid)>1
);
I like to use exists to check for multiples. With an index on passenger_id it may run faster than the query above.
select * from passenger_1038299 p
join flight_1038299 f on f.passenger_id = p.passenger_id
where exists (
select 1 from flight_1038299 f2
where f2.passenger_id = f.passenger_id
and f2.flight_id <> f.flight_id
)
Edit
Another way using the count window function:
select * from (
select *,
count() over (partition by p.passenger_id) cnt
from passenger_1038299 p
join flight_1038299 f on f.passenger_id = p.passenger_id
) t where cnt > 1
Another way with using analytic functions:
SELECT * FROM (
SELECT p.*, f.flight_id,
count(*) OVER (PARTITION BY f.passenger_id ) As number_of_flights
FROM passenger p
JOIN flight f
ON p.passenger_id = f.passenger_id
)
WHERE number_of_flights > 1
Demo: http://sqlfiddle.com/#!4/dab21/11
Try this way
Flight id should be multiple so it comma separated of column.
select a.*,b.flightid from passenger_1038299 a
join (select passengerid,Stuff((SELECT ', ' + s.flight_id
FROM flight_1038299 l
where c.passengerid = l.passengerid
FOR XML PATH('')),1,1,'') flightid from flight_1038299 as c group by c.passengerid having count(c.passengerid)>1) b on a.passengerid=b.passengerid

SQL - UNION, priority on the first select statement when doing order by

I'm trying to print out the results from the "GermanDB" Database first, while also showing everything from the Boston DB that was not in the German database. Can this be done in one query?
My query (the bold part functions but does not order the way I want)
select * from (
SELECT DISTINCT a.ProductRef
FROM GERMANDB.dbo.LOCATIONS AS a INNER JOIN GERMANDB.dbo.ITEMS AS b ON a.ProductRef = b.ProductRef
WHERE b.ACTIVE=1
) ta
UNION select * from
SELECT DISTINCT c.ProductRef
FROM BOSTONDB.dbo.LOCATIONS AS c INNER JOIN BOSTONDB.dbo.ITEMS AS d ON c.ProductRef = d.ProductRef
WHERE c.ACTIVE=1 (c.ProductRef NOT IN
(SELECT ProductRef FROM GERMANDB.dbo.ITEMS where ACTIVE=1))
) tb
order by ta.ProductRef** , tb.productRef
Just add one field to signal the priority. Like this:
select *, 0 as Priority from (
SELECT DISTINCT a.ProductRef
FROM GERMANDB.dbo.LOCATIONS AS a INNER JOIN GERMANDB.dbo.ITEMS AS b ON a.ProductRef = b.ProductRef
WHERE b.ACTIVE=1
) ta
UNION select *, 1 as Priority from
SELECT DISTINCT c.ProductRef
FROM BOSTONDB.dbo.LOCATIONS AS c INNER JOIN BOSTONDB.dbo.ITEMS AS d ON c.ProductRef = d.ProductRef
WHERE c.ACTIVE=1 (c.ProductRef NOT IN
(SELECT ProductRef FROM GERMANDB.dbo.ITEMS where ACTIVE=1))
) tb
order by Priority, ProductRef

Using CTE in a DELETE is not executing

Here is the original query that runs and runs:
;WITH includedCs_cte
AS
(
SELECT
x.PKey,
x.OKey,
y.CKey
FROM
#Permissions x
JOIN WHDATA.dbo.tb_DimC y
ON
x.PKey = y.PKey AND
x.OKey = y.OKey
)
, b_cte
AS
(
SELECT
i.OKey,
i.PKey
FROM
WHData.dbo.vw_FactCX b
INNER JOIN includedCs_cte i
ON
b.PKey = i.PKey AND
b.PlayCKey = i.CKey
WHERE b.DateKey >= #myLAST28DAYS
GROUP BY
i.OKey,
i.PKey
)
, POK_cte
AS
(
SELECT
i.OKey,
i.PKey
FROM
WHData.dbo.vw_FactCY b
INNER JOIN includedCs_cte i
ON
b.PKey = i.PKey AND
b.PlayCKey = i.CKey
WHERE b.DateKey >= #myLAST28DAYS
GROUP BY
i.OKey,
i.PKey
)
, includedOKeys
AS
(
SELECT *
FROM b_cte
UNION
SELECT * FROM POK_cte
)
DELETE FROM #Permissions
FROM #Permissions p
WHERE NOT EXISTS
(
SELECT 1
FROM includedOKeys x
WHERE
p.PKey = x.PKey AND
p.OKey = x.OKey
)
If I change the above to the below then it runs in less than 10 seconds. Why are these executing so differently?
;WITH includedCs_cte
AS
(
SELECT
x.PKey,
x.OKey,
y.CKey
FROM
#Permissions x
JOIN WHDATA.dbo.tb_DimC y
ON
x.PKey = y.PKey AND
x.OKey = y.OKey
)
, b_cte
AS
(
SELECT
i.OKey,
i.PKey
FROM
WHData.dbo.vw_FactCX b
INNER JOIN includedCs_cte i
ON
b.PKey = i.PKey AND
b.PlayCKey = i.CKey
WHERE b.DateKey >= #myLAST28DAYS
GROUP BY
i.OKey,
i.PKey
)
, POK_cte
AS
(
SELECT
i.OKey,
i.PKey
FROM
WHData.dbo.vw_FactCY b
INNER JOIN includedCs_cte i
ON
b.PKey = i.PKey AND
b.PlayCKey = i.CKey
WHERE b.DateKey >= #myLAST28DAYS
GROUP BY
i.OKey,
i.PKey
)
, includedOKeys
AS
(
SELECT *
FROM b_cte
UNION
SELECT * FROM POK_cte
)
SELECT *
INTO #includedOKeys
FROM includedOKeys
CREATE CLUSTERED INDEX ix_inclProdOper ON #includedOKeys(OKey, PKey)
DELETE FROM #Permissions
FROM #Permissions p
WHERE NOT EXISTS
(
SELECT 1
FROM #includedOKeys x
WHERE
p.PKey = x.PKey AND
p.OKey = x.OKey
)
A CTE is resolved when it is used. It means that if you use it twice in a query, it may get resolved twice. CTEs do not always get resolved once and cache in memory. SQL Server is free to execute the query as it sees fit.
In your case, it may be worse than that - because you have used it as a correlated subquery in an EXISTS clause, which is a row-by-row operation. This probably means the plan results in the CTE being resolved for EACH ROW of the #permissions table! That could well be where all the time will be going. Show Execution Plan (Ctrl-L) in SSMS is your friend here.
Check this SQLFiddle, which shows that NONE of the GUIDs are the same, even though the CTE only creates 3 rows. In fact, we get 18 distinct GUIDs.
with cte(guid,other) as (
select newid(),1 union all
select newid(),2 union all
select newid(),3)
select a.guid, a.other, b.guid guidb, b.other otherb
from cte a
cross join cte b
order by a.other, b.other;

How would that be possible to make this SQL Query simpler/shorter?

It should return some fields from the SystemTable and the LoadStatus column of the latest record in the ProcessHistory table. The relationship is 1 to many:
SELECT ST.[SystemDetailID], ST.[SystemName], LH.LatestLoadStatus
FROM [SystemTable] AS ST
LEFT OUTER JOIN
(
SELECT LHInner.LoadStatus AS LatestLoadStatus, LHInner.SystemDetailID FROM [dbo].[LoadHistory] AS LHInner
WHERE LHInner.LoadHistoryID in
(
SELECT LatestLoadHisotoryID FROM
(
SELECT MAX(LoadHistoryID) as LatestLoadHisotoryID, SystemDetailID FROM [dbo].[LoadHistory]
GROUP BY SystemDetailID
) l
)
) AS LH ON ST.SystemDetailID = LH.SystemDetailID
Thanks,
This is a greatest-n-per-group query.
One Approach
SELECT ST.[SystemDetailID],
ST.[SystemName],
LH.LatestLoadStatus
FROM [SystemTable] AS ST
OUTER APPLY (SELECT TOP 1 *
FROM [dbo].[LoadHistory] LH
WHERE ST.SystemDetailID = LH.SystemDetailID
ORDER BY LoadHistoryID DESC) LH
You can also use row_number
WITH LH
AS (SELECT *,
ROW_NUMBER() OVER (PARTITION BY SystemDetailID
ORDER BY LoadHistoryID DESC) RN
FROM [dbo].[LoadHistory])
SELECT ST.[SystemDetailID],
ST.[SystemName],
LH.LatestLoadStatus
FROM [SystemTable] AS ST
LEFT JOIN LH
ON LH.SystemDetailID = ST.SystemDetailID
AND LH.RN = 1
SELECT ST.[SystemDetailID], ST.[SystemName], LH.LatestLoadStatus
FROM [SystemTable] AS ST
INNER JOIN [dbo].[LoadHistory] AS LH
ON ST.SystemDetailID = LH.SystemDetailID
AND LH.LoadHistoryID IN
(SELECT MAX(LoadHistoryID) as LoadHistoryID
FROM [dbo].[LoadHistory]
GROUP BY SystemDetailID )