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

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

Related

How to optimize long running cte

I have one query that is taking 10 minute and giving me 6852104 records. How can I optimize it? I have added execution plan as well.
My query is like this:
WITH CTE (columns name
)
AS (
SELECT columns
FROM #tempTable b WITH (NOLOCK)
INNER JOIN physicaltable1 A ON A.ParentInvoiceItemId = b.InvoiceItemId
INNER JOIN physicaltable2 c ON c.LinkedInvoiceItemId = a.LinkedInvoiceItemId
AND c.HospitalId = B.Hospital_Id
UNION ALL
SELECT columns
FROM CTE LIP
JOIN physicaltable1 LIC ON LIP.ChildInvoiceItemId = LIC.ParentInvoiceItemId
INNER JOIN physicaltable12 LIH ON LIH.LinkedInvoiceItemId = LIC.LinkedInvoiceItemId
AND LIH.HospitalId = LIP.HospitalId
WHERE LIP.[Level] < 3
)
SELECT *
INTO #newtemptable
FROM CTE;

Select all records between two dates but one record on same day depending on plate

I have select query :
select
f.FirmaID,f.FirmaAdi,t.BelgeID,t.BelgeTuru,t.Tarih,t2.Plaka,t2.SasiNo,t4.AracMarka,t4.AracTip,case when x.Miktar=1 then 4 else x.miktar end as LastikAdet,
t3.CariKodu,t3.CariAdi,t3.CariGsm1,t3.CariGsm2,t3.CariTel1,t3.CariTel2,t3.CariAdres
from alsatr t WITH (NOLOCK)
left join Firma f WITH (NOLOCK) on f.FirmaID = t.AlsatrFirmaID
left join AracBilgi t2 WITH (NOLOCK) on t2.AracBilgiUID = t.AsAracBilgiUID and t2.AracBilgiID= t.AracBilgi
left join Cari t3 WITH (NOLOCK) on t.AsCariUID= t3.CariUID
left join Araclar t4 WITH (NOLOCK) on t4.AracID= t2.AB_AracID
outer apply
(select COUNT(1) soktak,Miktar FROM alsatD d WITH (NOLOCK)
where
d.AlsatDUID = t.AlsatrUID and d.AsStokKodu='LA-0001' group by Miktar) x
where
isnull(t3.FiloID,0) > 0
and t.Tarih between '04.30.2020' and '04.31.2020'
and t.BelgeTuru=55
and x.soktak > 0
and f.FirmaID not in (1,2,103,106,109,114)
order by t.Tarih desc, f.FirmaID desc, t.BelgeID desc
So I want to select all records between two days but I want to select one,latest record (maybe depends on last BelgeID ) on same day with same plate (plaka).
Enclose your query inside a CTE and use ROW_NUMBER() window function:
WITH cte AS (
<your query here>
)
SELECT
t.FirmaID, t.FirmaAdi, t.BelgeID, t.BelgeTuru, t.Tarih, t.Plaka, t.SasiNo, t.AracMarka,
t.AracTip, t.LastikAdet, t.CariKodu, t.CariAdi, t.CariGsm1, t.CariGsm2, t.CariTel1,
t.CariTel2, t.CariAdres
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Tarih, Plaka ORDER BY BelgeID DESC) rn
FROM cte
) t
WHERE t.rn = 1

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

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

selecting the max values based on a count

How can i retrieve the max of each ValueCount based on the firmid. I need the data to be output like so.
My code is below
SELECT
F.FirmID,
F.Name,
DL.ValueId,
DL.ValueName,
count(DL.ValueName) AS ValueCount
FROM
dbo.Jobs AS J
INNER JOIN DimensionValues AS DV ON
DV.CrossRef = J.JobId
INNER JOIN dbo.DimensionLists AS DL ON
DV.ValueId = DL.ValueId
INNER JOIN Firms AS F ON
F.FirmId = J.ClientFirmId
WHERE
DL.DimensionId = 4
GROUP BY
F.FirmID,
F.Name,
DL.ValueName,
DL.ValueId
this produces something like
firmid | value | count
1 1 5
1 2 10
2 3 1
2 1 6
i need to return back the records with 10 and 6.
EDIT : SQL 2005 answer deleted.
Then you could push your results into a temporary table (or table variable) and do something like this...
SELECT
*
FROM
TempTable
WHERE
ValueCount = (SELECT MAX(ValueCount) FROM TempTable AS Lookup WHERE FirmID = TempTable.FirmID)
Or...
SELECT
*
FROM
TempTable
INNER JOIN
(SELECT FirmID, MAX(ValueCount) AS ValueCount FROM TempTable GROUP BY FirmID) AS lookup
ON lookup.FirmID = TempTable.FirmID
AND lookup.ValueCount = TempTable.ValueCount
These will give multiple records if any ValueCount is tied with another for the same FirmID. As such, you could try this...
SELECT
*
FROM
TempTable
WHERE
value = (
SELECT TOP 1
value
FROM
TempTable as lookup
WHERE
FirmID = TempTable.FirmID
ORDER BY
ValueCount DESC
)
For this problem you need to produce the result set of the query in order to determine the Max ValueCount, then you need to do the query again to pull just the records with Max ValueCount. You can do this many way, like repeating the main query as subqueries, and in SQL Server 2005/2008 by using a CTE. I think using the subqueries gets a little messy and would prefer the CTE, but for SQL Server 2000 you don't have that as an option. So, I've used a temp table instead of a CTE. I run it once to get the MaxValueCount and save that into a temp table, then run the query again and join against the temp table to get just the record with MaxValueCount.
create table #tempMax
(
FirmID int,
MaxValueCount int
)
insert #tempMax
SELECT t.FirmID, MAX(t.ValueCount) AS MaxValueCount
FROM (
SELECT F.FirmID, F.Name, DL.ValueId, DL.ValueName
, count(DL.ValueName) AS ValueCount
FROM dbo.Jobs AS J
INNER JOIN DimensionValues AS DV ON DV.CrossRef = J.JobId
INNER JOIN dbo.DimensionLists AS DL ON DV.ValueId = DL.ValueId
INNER JOIN Firms AS F ON F.FirmId = J.ClientFirmId
WHERE DL.DimensionId = 4
GROUP BY F.FirmID, F.Name, DL.ValueName, DL.ValueId) t
SELECT t.FirmID, t.Name, t.ValueID, t.ValueName, t.ValueCount
FROM (
SELECT F.FirmID, F.Name, DL.ValueId, DL.ValueName
, count(DL.ValueName) AS ValueCount
FROM dbo.Jobs AS J
INNER JOIN DimensionValues AS DV ON DV.CrossRef = J.JobId
INNER JOIN dbo.DimensionLists AS DL ON DV.ValueId = DL.ValueId
INNER JOIN Firms AS F ON F.FirmId = J.ClientFirmId
WHERE DL.DimensionId = 4
GROUP BY F.FirmID, F.Name, DL.ValueName, DL.ValueId) t
INNER JOIN #tempMax m ON t.FirmID = m.FirmID and t.ValueCount = m.MaxValueCount
DROP TABLE #tempMax
You should be able to use a derived table for this:
SELECT F.FirmID,
F.Name,
DL.ValueId,
DL.ValueName,
T.ValueCount
FROM Jobs J
INNER JOIN DimensionValues DV
ON DV.Crossref = J.JobID
INNER JOIN DimensionList DL
ON DV.ValueID = DL.ValueID
INNER JOIN Firms F
ON F.FirmID = J.ClientFirmID
--derived table
INNER JOIN (SELECT FirmID, MAX(ValueName) ValueCount FROM DimensionList GROUP BY FirmID) T
ON T.FirmID = F.FirmID
WHERE DL.DimensionId = 4
TBL1 and TBL2 is your query:
SELECT *
FROM TBL1
WHERE
TBL1.ValueCount = (SELECT MAX(TBL2.ValueCount) FROM TBL2 WHERE TBL2.FIRMID = TBL1.FIRMID)

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 )