Checking against a table before query? - sql

In the following query, how could I do a sub query to find all categories in exp_categories that have a parent_id AND all categories that are a parent, but don't have any children, then use this instead of the AND c.parent_id != '0'?
SELECT c.cat_url_title
FROM exp_channel_titles as t
LEFT JOIN exp_category_posts AS cp ON cp.entry_id = t.entry_id
LEFT JOIN exp_categories AS c ON cp.cat_id = c.cat_id
WHERE t.url_title = 'hummingbird'
AND c.parent_id != '0'
AND c.cat_url_title != 'latest-work'
AND c.cat_url_title != 'best-selling-images'
LIMIT 1

Something like this?
SELECT c.cat_url_title
FROM exp_channel_titles as t
LEFT JOIN exp_category_posts AS cp ON cp.entry_id = t.entry_id
LEFT JOIN exp_categories AS c ON cp.cat_id = c.cat_id
WHERE t.url_title = 'hummingbird'
AND c.parent_id in (
select id from exp_categories where parent_id is not null
union
select id from exp_categories where id not in (
select parent_id from exp_categories
)
)
AND c.cat_url_title != 'latest-work'
AND c.cat_url_title != 'best-selling-images'
LIMIT 1

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?

Rewrite union query to a single query

I wondered if it was possible to write this as one query:
SELECT * FROM
(SELECT "markets".*
FROM "markets"
INNER JOIN "positions" ON "positions"."id" = "markets"."position_id"
INNER JOIN "players" ON "players"."id" = "positions"."player_id"
INNER JOIN "other_players" ON "other_players"."id" = "players"."other_player_id"
WHERE (markets.updated_at > '2021-01-10 11:50:14.136015')
AND "markets"."on_feed" = true
AND "markets"."deleted_at" IS NULL
UNION
SELECT "markets".*
FROM "markets"
WHERE (markets.updated_at > '2021-01-10 11:50:14.136015')
AND "markets"."on_feed" = true
AND "markets"."deleted_at" IS NOT NULL) results
ORDER BY results.updated_at DESC
There's a lot of overlap in the two queries. In the first one we want all markets that have those associations in place. For the 2nd query we don't really care if the associations are there or not.
SELECT * FROM "markets"
LEFT JOIN "positions" ON "positions"."id" = "markets"."position_id"
LEFT JOIN "players" ON "players"."id" = "positions"."player_id"
LEFT JOIN "other_players" ON "other_players"."id" = "players"."other_player_id"
WHERE markets.updated_at > '2021-01-10 11:50:14.136015'
AND "markets"."on_feed" = true
AND ("markets"."deleted_at" IS NOT NULL
OR "positions"."id" IS NOT NULL AND "players"."id" IS NOT NULL
AND "other_players"."id" IS NOT NULL)
ORDER BY markets.updated_at DESC
Use EXISTS instead:
SELECT m.*
FROM "markets" m
WHERE m.updated_at > '2021-01-10 11:50:14.136015' AND
markets."on_feed" = true AND
(m."deleted_at" IS NOT NULL OR
EXISTS (SELECT 1
FROM "positions" p JOIN
"players" pl
ON pl."id" = p."player_id" JOIN
"other_players" op
ON op."id" = p."other_player_id"
WHERE p."id" = m."position_id"
)
)
ORDER BY m.updated_at DESC

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

how to optimized without union clauses?

Is it possible to write below query without a union clause.
select ProductId,ImageName,ImageType, ROW_NUMBER() over (order by ProductId desc) RowId
from
(
select p.id ProductId ,p.pic_image ImageName,'pic_image' ImageType
from product p
left outer join iimages_edited pe on p.id = pe.[id]
where isnull(p.pic_image,'') <> '' and isnull(pe.pic_image,0)=0
union
select p.id ProductId,p.pic_bimage ImageName,'pic_bimage' ImageType
from product p
left outer join iimages_edited pe on p.id = pe.[id]
where isnull(p.pic_bimage,'') <> '' and isnull(pe.pic_bimage,0)=0
union
select p.id ProductId,p.pic_limage ImageName,'pic_limage' ImageType
from product p
left outer join iimages_edited pe on p.id = pe.[id]
where isnull(p.pic_limage,'') <> '' and isnull(pe.pic_limage,0)=0
union
select p.id ProductId,p.pic_blimage ImageName,'pic_blimage' ImageType
from product p
left outer join iimages_edited pe on p.id = pe.[id]
where isnull(p.pic_blimage,'') <> '' and isnull(pe.pic_blimage,0)=0
union
select p.id ProductId,p.pic_cimage ImageName,'pic_cimage' ImageType
from product p
left outer join iimages_edited pe on p.id = pe.[id]
where isnull(p.pic_cimage,'') <> '' and isnull(pe.pic_cimage,0)=0
)t
Above query has same table but different where condition, It is
possible to do it in a single query ?
Any help will be much appreciated !
Thanks in advance
It seems that you are repeating the same join and filters with differents columns each time. You can convert them to rows using UNPIVOT, on each table, before the join :
select pe.ProductId, p.ProductId, p.ImageName, p.ImageType, ROW_NUMBER()
over (order by p.ProductId desc) RowId
from (
select id as ProductId, ImageType, ImageName
from product
unpivot (
ImageType for ImageName
in (pic_image, pic_bimage, pic_limage, pic_blimage, pic_cimage)
) t
) as p
left outer join (
select id as ProductId, ImageType, ImageName
from iimages_edited
unpivot (
ImageType for ImageName
in (pic_image, pic_bimage, pic_limage, pic_blimage, pic_cimage)
) t
) as pe
on p.ImageType = pe.ImageType
and p.ProductId = pe.ProductId
where pe.ProductId is null
UNPIVOT filters null values, so ISNULL are probably not necessary.

How to correctly join table which may return more than one row

I have a table Items which have the following columns:
ItemId || AdminUserID || ItemName
And I try to join it with ItemAttributes:
ItemAttributeId || ItemId || AttributeValue
where one ItemId can have several ItemAttributeId values assigned to it.
I created procedure to retrieve item values from two tables:
SELECT
i.ItemID,
i.AdminUserID,
i.ItemName,
attr1.AttributeValue as IsForEmailRobotProcessingValue,
attr2.AttributeValue as RobotScheduledHoursValue -- HERE IS THE PROBLEM
FROM [dbo].[Items] i WITH (NOLOCK)
LEFT JOIN [dbo].ItemAttributes attr1 WITH(NOLOCK)
ON attr1.ItemID = i.ItemID and attr1.ItemAttributeID = 1
LEFT JOIN [dbo].ItemAttributes attr2 WITH(NOLOCK)
ON attr2.ItemID = i.ItemID and attr2.ItemAttributeID = 2
WHERE ((attr1.AttributeValue IS NOT NULL AND attr1.AttributeValue = 'true') OR
#OnlyForEmailRobotProcessing = 0)
ORDER BY ItemName
What I don't like here is that I LEFT JOIN two times the same table and created different aliases for each join according to the same ItemId. Is there any better way to LEFT JOIN only one time and created two different aliases for each ItemAttributeId? Thanks!
Try this:
SELECT
i.ItemID,
i.AdminUserID,
i.ItemName,
attr1.AttributeValue1 as IsForEmailRobotProcessingValue,
attr1.AttributeValue2 as RobotScheduledHoursValue
FROM [dbo].[Items] i WITH (NOLOCK)
LEFT JOIN
(select ItemId, (select AttributeValue
from [dbo].ItemAttributes a
where a.ItemId = b.ItemId and a.ItemAttributeID = 1) as AttributeValue1,
(select AttributeValue
from [dbo].ItemAttributes c
where c.ItemId = b.ItemId and c.ItemAttributeID = 2) as AttributeValue2
from [dbo].ItemAttributes b WITH(NOLOCK)
where b.ItemId = i.ItemID and b.ItemAttributeID in (1,2)
) attr1 on i.ItemId = attr1.ItemId
WHERE ((attr1.AttributeValue IS NOT NULL AND attr1.AttributeValue = 'true') OR
#OnlyForEmailRobotProcessing = 0)
ORDER BY ItemName