Optimize the SQL Statement with MAX() and VALUES() - sql

In the following case the target is to return the max value rating of a share:
SELECT DISTINCT sd.ShareId
, CASE
WHEN sd.GV01 IS NOT NULL OR sd.GV02 IS NOT NULL OR sd.GV03 IS NOT NULL THEN (
SELECT MAX(val)
FROM (VALUES (rmatMG.RankingId), (rmatSG.RankingId), (rmatFG.RankingId)) AS value(val)
WHERE val IS NOT NULL
)
END AS minRating
, sd.TradeValue
FROM dbo.MasterData sd
LEFT JOIN dbo.CfgRatingMatching rmMG ON sd.GV01 = rmMG.RatingIdOne
LEFT JOIN dbo.CfgRatingmatrix rmatMG ON rmMG.RatingIdCollMatrix = rmatMG.RankingId
LEFT JOIN dbo.CfgRatingMatching rmSG ON sd.GV02 = rmSG.RatingIdTwo
LEFT JOIN dbo.CfgRatingmatrix rmatSG ON rmSG.RatingIdCollMatrix = rmatSG.RankingId
LEFT JOIN dbo.CfgRatingMatching rmFG ON sd.GV03 = rmFG.RatingIdThree
LEFT JOIN dbo.CfgRatingmatrix rmatFG ON rmFG.RatingIdCollMatrix = rmatFG.RankingId
Do anyone have an idea how to optimize the code? I have a lot of data and the return of the list takes almost more than a minute. It takes too long.

Related

T-SQL Full Outer Join (sample provided)

I have some issues getting a full outer join to work in T-SQL. The left outer join part seems to be working okay, but the right outer join doesn't work as expected. Here's some sample data to test this on:
I have a table A with the following columns and data. The row marked with red is the row that cannot be found in table B.
And a second table B with the following columns and data. The rows marked with yellow are the rows that cannot be found in table A.
I am trying to join the tables using the following sql code:
select tableA.klientnr, tableA.uttakstype, tableA.uttaksnr, tableA.vareanr TableAItem,tableB.vareanr tableBitem, tableA.kvantum tableAquantity, tableB.totkvant tableBquantity
from tableA as tableA
full outer join tableB as tableB on tableA.klientnr=tableB.klientnr and tableA.uttakstype=tableB.uttakstype and tableA.uttaksnr=tableB.uttaksnr and tableA.vareanr=tableB.vareanr and tableB.IsDeleted=0
where tableA.UttaksNr=639779 and tableA.IsDeleted=0
The result of the sql is the following image. The row marked in red is the extra row from tableA that does show up, but I can't get the rows from table B to show up
Expected to have 2 extra rows
550 SA 639779 NULL 100059 NULL 0
550 SA 639779 NULL 103040 NULL 14
Later edit:
Would this be correct way to handle the full outer join where there's the header/line type of structure? Or can the query be optimized?
SELECT ISNULL(q1.accountid, q2.accountid) AccountId
,ISNULL(q1.klientnr, q2.klientnr) KlientNr
,ISNULL(q1.tilgangstype, q2.tilgangstype) 'Reception Type'
,ISNULL(q1.tilgangsnr, q2.tilgangsnr) 'Reception No'
,ISNULL(q1.dato, q2.dato) dato
,ISNULL(q1.LevNr, q2.LevNr) LevNr
,ISNULL(q1.Pakkemerke, q2.Pakkemerke) Pakkemerke
,ISNULL(q1.VareANr, q2.VareANr) VareANr
,ISNULL(q1.Ankomstdato,q2.Ankomstdato) 'Arrival Date'
,q1.Antall1
,q1.totkvant1
,q1.Antall2
,q1.totkvant2
,q2.Antall
,q2.totkvant
,q2.AntallTilFrys
,q2.TotKvantTilFrys
,ISNULL(q1.EksternKommentar1,q2.EksternKommentar1) EksternKommentar1
,q2.[Last Upsert]
FROM (
SELECT w700.accountid
,w700.klientnr
,w700.tilgangstype
,w700.tilgangsnr
,w700.dato
,w700.Ankomstdato
,w700.LevNr
,w700.pakkemerke
,w789.VareANr
,sum(IIF(w789.prognosetype = 1, w789.Antall, NULL)) AS Antall1
,sum(IIF(w789.prognosetype = 1, w789.totkvant, NULL)) AS totkvant1
,sum(IIF(w789.prognosetype = 2, w789.Antall, NULL)) AS Antall2
,sum(IIF(w789.prognosetype = 2, w789.totkvant, NULL)) AS totkvant2
,w700.EksternKommentar1
FROM trading.W789Prognosekjopstat AS w789
INNER JOIN trading.W700Tilgangshode AS w700 ON w700.AccountId = w789.AccountId
AND w700.KlientNr = w789.Klientnr
AND w700.Tilgangsnr = w789.Tilgangsnr
AND w700.Tilgangstype = w789.Tilgangstype
AND w700.IsDeleted = 0
WHERE w789.IsDeleted = 0
GROUP BY w700.accountid
,w700.klientnr
,w700.tilgangstype
,w700.tilgangsnr
,w700.dato
,w700.Ankomstdato
,w700.LevNr
,w700.pakkemerke
,w789.VareANr
,w700.EksternKommentar1
) q1
FULL OUTER JOIN (
SELECT w700.accountid
,w700.klientnr
,w700.tilgangstype
,w700.tilgangsnr
,w700.dato
,w700.Ankomstdato
,w700.LevNr
,w700.pakkemerke
,w702.VareANr
,w702.Antall
,w702.TotKvant
,w702.ValPris
,w702.AntallTilFrys
,w702.TotKvantTilFrys
,w700.EksternKommentar1
,(SELECT MAX(LastUpdateDate) FROM (VALUES (w702.createdAt),(w702.updatedAt)) AS UpdateDate(LastUpdateDate)) AS 'Last Upsert'
FROM trading.w702PrognoseKjop w702
INNER JOIN trading.W700Tilgangshode AS w700 ON w700.AccountId = w702.AccountId
AND w700.KlientNr = w702.Klientnr
AND w700.Tilgangsnr = w702.Tilgangsnr
AND w700.Tilgangstype = w702.Tilgangstype
AND w700.IsDeleted = 0
WHERE w702.IsDeleted = 0
) q2 ON q1.accountid = q2.accountid
AND q1.klientnr = q2.klientnr
AND q1.tilgangstype = q2.tilgangstype
AND q1.tilgangsnr = q2.tilgangsnr
AND q1.vareanr = q2.vareanr
WHERE totkvant1 IS NOT NULL
OR totkvant2 IS NOT NULL
OR totkvant IS NOT NULL
Filtering with full join is really tricky. Your where criteria are actually turning the full join into a left join.
You can do what you want by filtering before the join:
select a.klientnr, a.uttakstype, a.uttaksnr, a.vareanr a.tableAitem,
b.vareanr b.tableBitem, a.kvantum a.tableAquantity, b.totkvant b.tableBquantity
from (select a.*
from tableA a
where a.UttaksNr = 639779 and a.IsDeleted = 0
) a full join
(select b.*
from tableB b
where b.IsDeleted = 0
) b
on a.klientnr = b.klientnr and
a.uttakstype= b.uttakstype and
a.uttaksnr = b.uttaksnr and
a.vareanr = b.vareanr;

Remove row from SQL pivot when fields null

The following query below listed generates blank values in a row.
-- Simplify the pivot selection query by separating the query using a with clause
WITH pivot_data AS(
SELECT va.identity,
vc.units,
s.field_name "Sample ID",
s.id_text "Lab ID",
TO_CHAR(str.result_value, S_FORMATMASK_PACKAGE.s_FormatMask(vc.analysis, s.id_numeric))result_value
FROM sample s
LEFT OUTER JOIN client c ON c.id = s.client_id
LEFT OUTER JOIN samp_test_result str ON (s.id_numeric = str.id_numeric
AND s.id_text = str.id_text and str.result_value is not null)
LEFT OUTER JOIN versioned_analysis va ON (va.identity = str.analysis)
LEFT OUTER JOIN versioned_component vc ON (vc.analysis = va.identity
AND vc.analysis_version = va.analysis_version
AND vc.name = str.component_name)
WHERE s.fas_sample_type = sample_pkg.get_leaf_sample
AND s.status = sample_pkg.get_authorised_sample
AND s.flg_released = constant_pkg.get_true
AND vc.flg_report = constant_pkg.get_true
AND c.id = UPPER ('I000009')
AND s.ID_NUMERIC between TO_NUMBER(2126) and TO_NUMBER(12917) and str.result_value <> 0
)
SELECT pvt1.*
FROM(SELECT * FROM pivot_data PIVOT (MAX(result_value) result_value, MAX(units) units FOR identity IN('NIR_N' "Nitrogen",
'XRF_P' "Phosphorus",
'XRF_K' "Potassium",
'XRF_CA' "Calcium",
'XRF_MG' "Magnesium",
'XRF_S' "Sulphur",
'XRF_SI' "Silicon",
'XRF_ZN' "Zinc",
'XRF_MN' "Manganese",
'XRF_CU' "Copper",
'XRF_FE' "Iron"))) pvt1
How do I remove a row that contains null fields

Two select statements turn into one

I have set of two queries. In first query, if is separate from second, I got good results.
First query
SELECT *
FROM
(
SELECT nks.[Id]
, nks.[IdNarudzbe]
, nks.[IdArtikla] as artikal
, nks.[IdUsluge]
, nks.[Naziv]
, nks.Kolicina
, p.Naziv as kupac
, p.Id as kupacId
, p.Adresa
, p.Telefon
, nkz.[BrojDokumenta] AS nalog
, nkz.[BrojDokumentaKroz] AS nalogKroz
, nkz.[RokIsporuke]
, nkz.[IdNastaloOdDokumenta]
, d.Naziv as drzava
FROM [dbo].[NarudzbaKupacaStavke] nks
LEFT JOIN [dbo].[NarudzbeKupacaZaglavlje] nkz
ON nkz.Id = nks.IdNarudzbe
LEFT JOIN dbo.Partneri p
ON nkz.IdKupac = p.Id
LEFT JOIN dbo.Drzave d
ON p.IdDrzava = d.Id
WHERE idArtikla IN ('FP80PUR-08', 'FP80PUR-09', 'FP80PUR-12')
AND nkz.[VrstaDokumenta] = 'PRO'
AND nkz.StatusArhive = 0
--...
from first query nkz.[IdNastaloOdDokumenta] is important to second
SELECT BrojDokumenta
, BrojDokumentaKroz
FROM .[dbo].[NarudzbeKupacaZaglavlje]
where id = nkz.[IdNastaloOdDokumenta]
For ex. In first query I got nkz.[IdNastaloOdDokumenta] = 20. Number 20 I use in second query in where statement, and value I get from BrojDokumenta, I would like to join to first query.
I was wondering if is possible to make one query out of these two. I think I can not union operator because number of column from these two queries don't match.
The same table, and the same columns are already in the first query. Perhaps you want a self-join, like this:
FROM [dbo].[NarudzbaKupacaStavke] nks
LEFT JOIN [dbo].[NarudzbeKupacaZaglavlje] nkz
ON nkz.Id = nks.IdNarudzbe
LEFT JOIN [dbo].[NarudzbeKupacaZaglavlje] nkz2
ON nkz2.Id = nkz.[IdNastaloOdDokumenta]
LEFT JOIN dbo.Partneri p
ON nkz.IdKupac = p.Id
LEFT JOIN dbo.Drzave d
ON p.IdDrzava = d.Id
WHERE idArtikla IN ('FP80PUR-08', 'FP80PUR-09', 'FP80PUR-12')
AND nkz.[VrstaDokumenta] = 'PRO'
AND nkz.StatusArhive = 0

Group By clause error in Select query

Given below is my select query in PostgreSQL
SELECT
gtab12.AcGrCode,
gtab12.AcId,
gtab12.AcName,
gtab11.AcgrName,
gtab16.VrDate,
gtab16.PDC,
cast(gtab16.VrDate as char(12)) as vdate,
gtab16.VrNo,
gtab16.Refno,
gtab02.VrName,
gtab17.Narr,
CASE WHEN gtab16.VrId = 6 THEN 0::decimal ELSE gtab17.Dr::decimal END AS Dr,
CASE WHEN gtab16.VrId = 6 THEN 0::decimal ELSE gtab17.Cr::decimal END AS Cr,
gtab16.AcyrId, gtab16.VrId,
coalesce(SUM(gtab17.Dr), 0::money) AS OpDr,
coalesce(SUM(gtab17.Cr), 0::money) AS OpCr ,
coalesce(SUM(gtab17.Dr), 0::money)AS OpperDr,
coalesce(SUM(gtab17.Cr), 0::money)AS OpperCr,
gtab47.AreaName,
gtab16.JrmId
FROM
gtab16
INNER JOIN gtab02 ON gtab16.VrId = gtab02.VrId
INNER JOIN gtab17 ON gtab16.JrMId = gtab17.JrmId
INNER JOIN gtab12 ON gtab17.AcId = gtab12.AcId
INNER JOIN gtab11 ON gtab12.AcGrCode = gtab11.AcgrCode
INNER JOIN gtab01 ON gtab16.AcyrId = gtab01.AcYrId
LEFT OUTER JOIN gtab22 ON gtab16.RepId = gtab22.RepId
LEFT OUTER JOIN gtab47 ON gtab12.AreaId = gtab47.AreaId
WHERE
(gtab17.AcId = gtab12.AcId) and gtab16.BranchID = 1 And vrdate Between
Cast('2014-04-01' AS timestamp) AND Cast('2014-09-27' AS timestamp) AND
(gtab16.AcYrId = 7) AND gtab16.VrId <> 6 And gtab12.acid <> 0
when executing am getting this error
ERROR: column "gtab12.acgrcode" must appear in the GROUP BY clause or
be used in an aggregate function
Note : before modifying this query the aggreagte functions are gathering from sub selects see it here
You are using aggregate functions (SUM) in some columns so you need to use aggregates functions on other ones or group by columns.
Bye, David.

another union all selecting all the rows that have not already been selected

Right now i have 2 select statements that are joined by a union what i was hopping to do was maybe name the first query like query1 and the second one query2 and then in my third query do a where bookno not in query1 or query2.
SELECT distinct t0.BOOKNO, t0.PaxName, t0.Locator, t0.FDATE7,
t0.BOARD, t0.ALIGHT, t0.AIRLINE, t0.FNUMBR, t0.DEP,
t0.ARR, t0.TOUR, t0.ROUTE,
t1.tour, t1.route, t1.sfrom , t1.sto,t1.seq,t0.seq, 'yes'
FROM
( SELECT TOP (100) PERCENT test.dbo.BNAMES.BOOKNO, RTRIM(test.dbo.BNAMES.SRNAME) + '/' + RTRIM(test.dbo.BNAMES.FIRST) + RTRIM(test.dbo.BNAMES.TITLE)
AS PaxName, test.dbo.PNRS.PNR AS Locator, test.dbo.PNRSECTORS.FDATE7, test.dbo.PNRSECTORS.BOARD, test.dbo.PNRSECTORS.ALIGHT,
test.dbo.PNRSECTORS.AIRLINE, test.dbo.PNRSECTORS.FNUMBR, test.dbo.PNRSECTORS.DEP, test.dbo.PNRSECTORS.ARR, test.dbo.BOOKINGS.TOUR,
test.dbo.BOOKINGS.ROUTE, test.dbo.BSTAGES.SEQ,(test.dbo.PNRSECTORS.BOARD + test.dbo.PNRSECTORS.ALIGHT) as both
FROM test.dbo.BOOKINGS LEFT OUTER JOIN
test.dbo.BNAMES ON test.dbo.BOOKINGS.BOOKNO = test.dbo.BNAMES.BOOKNO LEFT OUTER JOIN
test.dbo.BSTAGES ON test.dbo.BNAMES.BOOKNO = test.dbo.BSTAGES.BOOKNO LEFT OUTER JOIN
test.dbo.PNRSECTORS ON test.dbo.BSTAGES.SCODE = test.dbo.PNRSECTORS.SKEY LEFT OUTER JOIN
test.dbo.PNRS ON test.dbo.PNRSECTORS.PNRKEY = test.dbo.PNRS.PNRKEY
WHERE (test.dbo.BSTAGES.STYPE = 3)
ORDER BY test.dbo.BOOKINGS.BOOKNO, test.dbo.BNAMES.SEQ, locator
) t0
INNER JOIN ( SELECT TOUR, ROUTE, OFFSET, SEQ, SCODE, SFROM, STO, (SFROM + STO) AS BOTH
FROM test.dbo.TSTAGES
) t1 ON t1.tour = t0.tour and t1.route = t0.route and (t0.both = t1.both)
union all
SELECT distinct t0.BOOKNO, t0.PaxName, t0.Locator, t0.FDATE7,
t0.BOARD, t0.ALIGHT, t0.AIRLINE, t0.FNUMBR, t0.DEP,
t0.ARR, t0.TOUR, t0.ROUTE,
t1.tour, t1.route, t1.sfrom , t1.sto,t1.seq,t0.seq,'YES'
FROM
( SELECT TOP (100) PERCENT test.dbo.BNAMES.BOOKNO, RTRIM(test.dbo.BNAMES.SRNAME) + '/' + RTRIM(test.dbo.BNAMES.FIRST) + RTRIM(test.dbo.BNAMES.TITLE)
AS PaxName, test.dbo.PNRS.PNR AS Locator, test.dbo.PNRSECTORS.FDATE7, test.dbo.PNRSECTORS.BOARD, test.dbo.PNRSECTORS.ALIGHT,
test.dbo.PNRSECTORS.AIRLINE, test.dbo.PNRSECTORS.FNUMBR, test.dbo.PNRSECTORS.DEP, test.dbo.PNRSECTORS.ARR, test.dbo.BOOKINGS.TOUR,
test.dbo.BOOKINGS.ROUTE, test.dbo.BSTAGES.SEQ,(test.dbo.PNRSECTORS.BOARD + test.dbo.PNRSECTORS.ALIGHT) as both
FROM test.dbo.BOOKINGS LEFT OUTER JOIN
test.dbo.BNAMES ON test.dbo.BOOKINGS.BOOKNO = test.dbo.BNAMES.BOOKNO LEFT OUTER JOIN
test.dbo.BSTAGES ON test.dbo.BNAMES.BOOKNO = test.dbo.BSTAGES.BOOKNO LEFT OUTER JOIN
test.dbo.PNRSECTORS ON test.dbo.BSTAGES.SCODE = test.dbo.PNRSECTORS.SKEY LEFT OUTER JOIN
test.dbo.PNRS ON test.dbo.PNRSECTORS.PNRKEY = test.dbo.PNRS.PNRKEY
WHERE (test.dbo.BSTAGES.STYPE = 1)
ORDER BY test.dbo.BOOKINGS.BOOKNO, test.dbo.BNAMES.SEQ, locator
) t0
INNER JOIN ( SELECT TOUR, ROUTE, OFFSET, SEQ, SCODE, SFROM, STO, (SFROM + STO) AS BOTH
FROM test.dbo.TSTAGES
) t1 ON t1.tour = t0.tour and t1.route = t0.route and t1.seq = t0.seq and (t0.both = t1.both)
order by bookno
END
How about using WITH? You can declare you queries, join them with UNION and them search for the ones not there.
Take a look here: Multiple Select Statements using SQL Server 2005 "WITH" Statement . It should help you get started.
By using WITH statement, you will isolate logic of your queries, making your overall query more understandable.
just wrap your logic around what you wrote:
select bookno
where key not in (
your big select statement...
)