Change the SELECT in WHERE clause to another solution - sql

I want to make my query better. What opportunities that I have to change this code for a faster one?
SELECT sn
FROM package p
WHERE StatusID = 1
AND ( NOT EXISTS( SELECT * FROM packagedetail pd
WHERE pd.packageID = p.ID AND packageDetailStatus = 12 )
OR ( EXISTS ( SELECT * FROM packagedetail pd
WHERE pd.packageID = p.ID AND packageDetailStatus = 12)
AND EXISTS ( SELECT * FROM unit u JOIN unitDetail ON u.ID = ud.unitID
WHERE (ud.InmostPackageID = p.ID OR ud.OutmostPackageID = p.ID)
AND u.UnitStateID in (8120, 8130, 8140)
)
)
)
( I know this is so ugly, but I want to know, how can I improve my skills )

One simplification that you can do is to not repeat the NOT EXISTS subquery again.
The below query is semantically equivalent to yours:
SELECT p.sn
FROM package p
WHERE p.StatusID = 1
AND (
NOT EXISTS(SELECT * FROM packagedetail pd
WHERE pd.packageID = p.ID AND packageDetailStatus = 12)
OR
EXISTS (SELECT * FROM unit u JOIN unitDetail ON u.ID = ud.unitID
WHERE (ud.InmostPackageID = p.ID OR ud.OutmostPackageID = p.ID) AND u.UnitStateID in (8120, 8130, 8140))
);
because:
(NOT X) OR (X AND Y) = (NOT X) OR Y

An alternative that might make it easier to read:
SELECT sn
FROM
package p
cross apply
(select
exists_packagedetail =case when exists (
SELECT *
FROM packagedetail pd
WHERE pd.packageID = p.ID AND packageDetailStatus = 12
) then 1 else 0 end
,exists_unitdetail =case when exists (
SELECT *
FROM
unit u
JOIN unitDetail ON u.ID = ud.unitID
WHERE (ud.InmostPackageID = p.ID OR ud.OutmostPackageID = p.ID) AND u.UnitStateID in (8120, 8130, 8140)
)then 1 else 0 end
) as q1
WHERE StatusID = 1 and (q1.exists_unitdetail=1 or q1.exists_packagedetail=0)

Related

WHERE not null for nested column SQL

I have a select statement with a nested column called Contents
EDIT: this is the full statement, just need results back without Contents at null.
Playlists = (
Select pl.Id as Id
,pl.Name as Name
,f.[Url] as PrimaryImageUrl
,up.Id as MemberId
,up.ProfessionalName
,up.AvatarUrl
,Contents = ( select c.Id as Id
,c.Name as Name
,c.ContentImageUrl as ImageUrl
,c.Price as Price
,c.BPM as BPM
,f.Id as 'File.Id'
,f.Url as 'File.Name'
,g.Id as 'Genre.Id'
,g.Name as 'Genre.Name'
,kt.Id as 'KeyType.Id'
,kt.Name as 'KeyType.Name'
,tt.Id as 'TrackType.Id'
,tt.Name as 'TrackType.Name'
,TotalCount = count(c.Id)Over()
from dbo.Content c
inner join dbo.PlayListContents pm on c.Id = pm.ContentId and pm.PlaylistId = pl.Id
inner join dbo.Files f on c.ContentFileId = f.Id
inner join dbo.Genres g on c.GenreTypeId = g.Id
inner join dbo.KeyType kt on c.KeyTypeId = kt.Id
inner join dbo.TrackType tt on tt.Id = c.TrackTypeId
WHERE (NOT EXISTS (SELECT b.Bpm
FROM #Bpm AS b
WHERE b.Bpm IS NOT NULL)
OR c.Bpm IN (SELECT * FROM #Bpm))
AND (NOT EXISTS (SELECT p.Price
FROM #Price AS p
WHERE p.Price IS NOT NULL)
OR c.Price <= ANY(SELECT * FROM #Price ))
AND (NOT EXISTS (SELECT gt.GenreTypeId
FROM #GenreTypeId AS gt
WHERE gt.GenreTypeId IS NOT NULL)
OR g.Id IN (SELECT * FROM #GenreTypeId))
AND (NOT EXISTS (SELECT kt.KeyTypeId
FROM #KeyTypeId AS kt
WHERE kt.KeyTypeId IS NOT NULL)
OR kt.Id IN (SELECT * FROM #KeyTypeId))
AND (NOT EXISTS (SELECT tt.TrackTypeId
FROM #TrackTypeId AS tt
WHERE tt.TrackTypeId IS NOT NULL)
OR tt.Id IN (SELECT * FROM #TrackTypeId))
for json path
)
from dbo.Playlist pl
inner join dbo.UserProfiles up on pl.UserId = up.UserId
inner join [dbo].[Files] as f ON pl.[PrimaryImageId] = f.[Id]
where ( pl.Name LIKE '%' + #SearchInput + '%')
order by newId()
For Json path)
Right now, the result set will bring back objects with some having Contents at null.
I tried to write out a WHERE Contents IS NOT NULL but this doesn't work. What am I missing?

Select sql statement for Mysql

I have this bit of sql
SELECT pd.id, pd.title, pd.fname, pd.lname, pd.DOB, pd.phone_home, pd.phone_biz, pd.phone_contact, pd.phone_cell, pd.sex, pd.email, pd.pid, f.form_id, ldf1.field_value AS autoleaxis, ldf2.field_value AS autolecyl
FROM patient_data pd
LEFT JOIN forms f ON pd.pid = f.pid
LEFT JOIN `lbf_data` ldf1 ON ldf1.form_id = f.form_id
LEFT JOIN `lbf_data` ldf2 ON ldf1.form_id = ldf2.form_id
WHERE (
f.form_name = 'Opthalmology'
AND ldf1.field_id = 'autoleaxis'
AND ldf2.field_id = 'autolecyl'
)
OR (
f.form_id IS NULL
AND ldf1.field_id IS NULL
AND ldf2.field_id IS NULL
)
ORDER BY pd.pid
Which is for a MySQL Database. It works ok except it is returning more than one record per person in some cases as they have more than one form_id. How do I restrict it so that it only returns the records for highest form_id that the person has or form_id set to null if there isn't one. Thanks
You can use subquery in LEFT JOIN, as with:
SELECT *
FROM patient_data pd
LEFT JOIN
(
select max(form_id) as form_id, pid, form_name
from forms as f2
) as f
ON pd.pid = f.pid
LEFT JOIN `lbf_data` ldf1 ON ldf1.form_id = f.form_id
LEFT JOIN `lbf_data` ldf2 ON ldf1.form_id = ldf2.form_id
WHERE (
f.form_name = 'Opthalmology'
AND ldf1.field_id = 'autoleaxis'
AND ldf2.field_id = 'autolecyl'
)
OR (
f.form_id IS NULL
AND ldf1.field_id IS NULL
AND ldf2.field_id IS NULL
)
ORDER BY pd.pid
You can test in here

Struggling with left join

I'm struggling with left joining the earliest row in this left join.
The results are showing a 2011 date, but i know for a fact this particular row should be returning 2008.
SELECT TOP 1000
f.name as [Franchisee]
,p.paid_date as paid_date
FROM franchisees_franchisee f
OUTER APPLY (SELECT TOP 1 *
FROM era_project_invoice_payment p
WHERE f.franchiseeid = p.franchiseeid
and p.deleted = 0 and p.payment_confirmed = 1
ORDER BY p.eraprojectinvoicepaymentid ASC) p
where
f.deleted = 0
and f.name LIKE '%VKlinkosch%'
Below returns the correct, 2008 date.
SELECT TOP 1000
f.name as [Franchisee]
,min(p.paid_date) as paid_date
from [era_uat_shared].[dbo].[franchisees_franchisee] f
left join era_project_invoice_payment p
on f.franchiseeid = p.franchiseeid
where f.deleted = 0
and f.name LIKE '%VKlinkosch%'
GROUP BY f.name
Problem is, I need more than just the Paid Date from the payments table! :(
SELECT
f.name as [Franchisee]
, p.*
FROM franchisees_franchisee f
INNER JOIN
(
SELECT
ROW_NUMBER() OVER (PARTITION BY franchiseeid ORDER BY paid_date ASC) rn
, p.*
FROM
era_project_invoice_payment p
WHERE
deleted = 0
AND payment_confirmed = 1
) p
ON
f.franchiseeid = p.franchiseeid
AND f.deleted = 0
AND f.name LIKE '%VKlinkosch%'
AND p.rn = 1

Alternate way of Exists with Having clause

The below query is to retrieve the records whose (SGT_DISBURSEMENT_REQUEST) count is only one. It is working great. But performance wise it didn't took so much of time since we have 100 000 records.
Is there any better way to do it?
SELECT PA.PERSON_ID,
PA.PERSON_ACCOUNT_ID,
DR.DISBURSEMENT_REQUEST_ID,
SUM
(
ISNULL(CD.EE_PRE_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_PRE_TAX_AMT,0)
) AS EE_PRE_TAX_CONTRIB,
DD.PRE_TAX_AMOUNT AS DISB_DTL_PRE_TAX_AMOUNT,
SUM
( ISNULL(CD.EE_POST_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_POST_TAX_AMT,0)
) AS EE_POST_TAX_CONTRIB,
DD.POST_TAX_AMOUNT AS DISB_DTL_POST_TAX_AMOUNT
FROM SGT_DISBURSEMENT_REQUEST DR
INNER JOIN SGT_DISBURSEMENT_DETAIL DD ON DR.DISBURSEMENT_REQUEST_ID = DD.DISBURSEMENT_REQUEST_ID
INNER JOIN SGT_PERSON_ACCOUNT PA ON PA.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID
INNER JOIN SGT_CONTRIB_DTL CD ON CD.PERSON_ACCOUNT_ID = PA.PERSON_ACCOUNT_ID
WHERE DR.REQUEST_CATEGORY_VALUE = 'REFD' AND
DD.DETAIL_CATEGORY_VALUE = 'REFD' AND
CD.STATUS_VALUE = 'VALD' AND
CD.POSTED_DATE <= DR.ACCEPTED_TO_PAYROLL_DATE AND
DR.DISBURSEMENT_STATUS_VALUE <> 'CANL' AND
EXISTS
(
SELECT 1 FROM SGT_DISBURSEMENT_REQUEST SDR1
INNER JOIN SGT_DISBURSEMENT_DETAIL SDD1 ON SDD1.DISBURSEMENT_REQUEST_ID = SDR1.DISBURSEMENT_REQUEST_ID
WHERE SDR1.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID and SDD1.DETAIL_CATEGORY_VALUE = DD.DETAIL_CATEGORY_VALUE
GROUP BY SDR1.PERSON_ACCOUNT_ID
HAVING COUNT(*) = 1
)
GROUP BY
PA.PERSON_ID, PA.PERSON_ACCOUNT_ID, DR.DISBURSEMENT_REQUEST_ID, DD.PRE_TAX_AMOUNT, DD.POST_TAX_AMOUNT
For Performance improvement you can have the Filter Conditions in the Join Clause, instead of where clause. In this case each join will restrict the results to even lesser number of rows.
SELECT PA.PERSON_ID,
PA.PERSON_ACCOUNT_ID,
DR.DISBURSEMENT_REQUEST_ID,
SUM
(
ISNULL(CD.EE_PRE_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_PRE_TAX_AMT,0)
) AS EE_PRE_TAX_CONTRIB,
DD.PRE_TAX_AMOUNT AS DISB_DTL_PRE_TAX_AMOUNT,
SUM
( ISNULL(CD.EE_POST_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_POST_TAX_AMT,0)
) AS EE_POST_TAX_CONTRIB,
DD.POST_TAX_AMOUNT AS DISB_DTL_POST_TAX_AMOUNT
FROM SGT_DISBURSEMENT_REQUEST DR
INNER JOIN SGT_DISBURSEMENT_DETAIL DD ON DR.DISBURSEMENT_REQUEST_ID = DD.DISBURSEMENT_REQUEST_ID AND DR.REQUEST_CATEGORY_VALUE = 'REFD' AND
DD.DETAIL_CATEGORY_VALUE = 'REFD' AND DR.DISBURSEMENT_STATUS_VALUE <> 'CANL'
INNER JOIN SGT_PERSON_ACCOUNT PA ON PA.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID
INNER JOIN SGT_CONTRIB_DTL CD ON CD.PERSON_ACCOUNT_ID = PA.PERSON_ACCOUNT_ID AND CD.STATUS_VALUE = 'VALD' AND
CD.POSTED_DATE <= DR.ACCEPTED_TO_PAYROLL_DATE
WHERE EXISTS
(
SELECT 1 FROM SGT_DISBURSEMENT_REQUEST SDR1
INNER JOIN SGT_DISBURSEMENT_DETAIL SDD1 ON SDD1.DISBURSEMENT_REQUEST_ID = SDR1.DISBURSEMENT_REQUEST_ID
WHERE SDR1.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID and SDD1.DETAIL_CATEGORY_VALUE = DD.DETAIL_CATEGORY_VALUE
GROUP BY SDR1.PERSON_ACCOUNT_ID
HAVING COUNT(*) = 1
)
GROUP BY
PA.PERSON_ID, PA.PERSON_ACCOUNT_ID, DR.DISBURSEMENT_REQUEST_ID, DD.PRE_TAX_AMOUNT, DD.POST_TAX_AMOUNT
if you use count over it should give you the same result and be better for performance:
select * from (
SELECT PA.PERSON_ID,
PA.PERSON_ACCOUNT_ID,
DR.DISBURSEMENT_REQUEST_ID,
SUM
(
ISNULL(CD.EE_PRE_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_PRE_TAX_AMT,0)
) AS EE_PRE_TAX_CONTRIB,
DD.PRE_TAX_AMOUNT AS DISB_DTL_PRE_TAX_AMOUNT,
SUM
( ISNULL(CD.EE_POST_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_POST_TAX_AMT,0)
) AS EE_POST_TAX_CONTRIB,
DD.POST_TAX_AMOUNT AS DISB_DTL_POST_TAX_AMOUNT
,count(*) over(partition by PA.PERSON_ACCOUNT_ID ) as ct
FROM SGT_DISBURSEMENT_REQUEST DR
INNER JOIN SGT_DISBURSEMENT_DETAIL DD ON DR.DISBURSEMENT_REQUEST_ID = DD.DISBURSEMENT_REQUEST_ID
INNER JOIN SGT_PERSON_ACCOUNT PA ON PA.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID
INNER JOIN SGT_CONTRIB_DTL CD ON CD.PERSON_ACCOUNT_ID = PA.PERSON_ACCOUNT_ID
WHERE DR.REQUEST_CATEGORY_VALUE = 'REFD' AND
DD.DETAIL_CATEGORY_VALUE = 'REFD' AND
CD.STATUS_VALUE = 'VALD' AND
CD.POSTED_DATE <= DR.ACCEPTED_TO_PAYROLL_DATE AND
DR.DISBURSEMENT_STATUS_VALUE <> 'CANL'
GROUP BY
PA.PERSON_ID, PA.PERSON_ACCOUNT_ID, DR.DISBURSEMENT_REQUEST_ID, DD.PRE_TAX_AMOUNT, DD.PRE_TAX_AMOUNT, DD.POST_TAX_AMOUNT
) as x
where x.ct = 1
I would materialize this to a #temp
SELECT DR1.PERSON_ACCOUNT_ID, SDD1.DETAIL_CATEGORY_VALUE
FROM SGT_DISBURSEMENT_REQUEST SDR1
JOIN SGT_DISBURSEMENT_DETAIL SDD1
ON SDD1.DISBURSEMENT_REQUEST_ID = SDR1.DISBURSEMENT_REQUEST_ID
GROUP BY SDR1.PERSON_ACCOUNT_ID, SDD1.DETAIL_CATEGORY_VALUE
HAVING COUNT(*) = 1
join #temp
on #temp.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID
and #temp.DETAIL_CATEGORY_VALUE = DD.DETAIL_CATEGORY_VALUE

SQL Select Into #Temp

I have a complex SQL query that works. It's like
SELECT * FROM Site s
JOIN (
SELECT DISTINCT z.Value FROM Doc z
JOIN (
SELECT x.DocumentID FROM Doc x
JOIN (
SELECT DocumentID, MAX(VERSION) AS VERSION
FROM Doc GROUP BY DocumentID) y ON y.DocumentID = x.DocumentID
WHERE DocumentTypeID = 78 AND MetadataTypeID = 22 AND VALUE > GETDATE() AND y.Version = x.Version
) a ON z.DocumentID = a.DocumentID
WHERE MetadataTypeID = 2
) b ON b.Value = s.SiteID
WHERE SiteID > 0
It does what I want it to do. But when I wrap it in
SELECT * INTO #Temp FROM ()
I get an incorrect syntax near ')'.
I'm confused. I just want to put the results into a temp table so I can do further work on it. Why doesn't it work?
You're missing an alias for subquery.
SELECT * INTO #MyTempTable
FROM
(
SELECT * FROM Site s
JOIN (
SELECT DISTINCT z.Value FROM Doc z
JOIN (
SELECT x.DocumentID FROM Doc x
JOIN (
SELECT DocumentID, MAX(VERSION) AS VERSION
FROM Doc GROUP BY DocumentID) y ON y.DocumentID = x.DocumentID
WHERE DocumentTypeID = 78 AND MetadataTypeID = 22 AND VALUE > GETDATE() AND y.Version = x.Version
) a ON z.DocumentID = a.DocumentID
WHERE MetadataTypeID = 2
) b ON b.Value = s.SiteID
WHERE SiteID > 0
) AS DT
select * into TBL_name from
( SELECT * FROM Site s
JOIN (
SELECT DISTINCT z.Value FROM Doc z
JOIN (
SELECT x.DocumentID FROM Doc x
JOIN (
SELECT DocumentID, MAX(VERSION) AS VERSION
FROM Doc GROUP BY DocumentID) y ON y.DocumentID = x.DocumentID
WHERE DocumentTypeID = 78 AND MetadataTypeID = 22 AND VALUE > GETDATE() AND y.Version = x.Version
) a ON z.DocumentID = a.DocumentID
WHERE MetadataTypeID = 2
) b ON b.Value = s.SiteID
WHERE SiteID > 0)al