translating sql sub query to join - sql

I had a long query, I short it out by using joins instead and resultant query is as below but still it has sub query. How to convert this sub query to join
SELECT
pav.post_id as Id, img.path as Path, attr.name as Name, pc.title as Category, pav.value_text as Valuess, post.created_on as createdOn
FROM
postings post inner join post_attributes_values pav on post.post_id = pav.post_id
left outer join images img on post.post_id = img.post_id and img.sequence='1'
inner join attributes attr on pav.attr_id = attr.attr_id
inner join categories_parent_categories pc on attr.cat_id = pc.category_id
where
pav.post_id in (select distinct post_id from post_attributes_values where value_text = 'SFX')

After reading your last comment to Matei's answer I have come to realize that you actually want ALL the posts where one of the attributes has value of 'SFX'. If I understood correctly, your only alternative is to add derived table and join by post_id:
SELECT pav.post_id AS Id,
img.path AS Path,
attr.name AS Name,
pc.title AS Category,
pav.value_text AS Valuess,
post.created_on AS createdOn
FROM postings post
INNER JOIN post_attributes_values pav
ON post.post_id = pav.post_id
LEFT OUTER JOIN images img
ON post.post_id = img.post_id
AND img.sequence = '1'
INNER JOIN attributes attr
ON pav.attr_id = attr.attr_id
INNER JOIN categories_parent_categories pc
ON attr.cat_id = pc.category_id
INNER JOIN
(
SELECT DISTINCT post_id
FROM post_attributes_values
WHERE value_text = 'SFX'
) sfxPosts
ON pav.post_id = sfxPosts.post_id
(Query reformatted thanks to instant sql formatter.)

Maybe this? Please test it
SELECT
pav.post_id as Id, img.path as Path, attr.name as Name, pc.title as Category, pav.value_text as Valuess, post.created_on as createdOn
FROM
postings post
inner join post_attributes_values pav on post.post_id = pav.post_id AND pav.value_text = 'SFX'
left outer join images img on post.post_id = img.post_id and img.sequence='1'
inner join attributes attr on pav.attr_id = attr.attr_id
inner join categories_parent_categories pc on attr.cat_id = pc.category_id

Related

I need to group (tbl_types.name AS type) in a same row (postgres 14)

I need help with a select in postgres, I need to group X types into a single line, for example: type: multiple, trully, I need help on the type column
SELECT tbl_questions.id AS id,
tbl_questions.question AS question,
tbl_questions.year AS year,
tbl_question_responses.response_id AS response_id,
tbl_responses.response AS response_content,
tbl_responses.response_type AS response,
tbl_subjects.name AS subject,
tbl_categories.name AS category,
tbl_types.name AS type,
tbl_institutions.name AS institution
FROM tbl_questions
INNER JOIN tbl_question_responses ON tbl_questions.id = tbl_question_responses.question_id
INNER JOIN tbl_responses ON tbl_question_responses.response_id = tbl_responses.id
INNER JOIN tbl_question_subjects ON tbl_questions.id = tbl_question_subjects.question_id
INNER JOIN tbl_subjects ON tbl_subjects.id = tbl_question_subjects.subject_id
INNER JOIN tbl_question_categories ON tbl_questions.id = tbl_question_categories.question_id
INNER JOIN tbl_categories ON tbl_categories.id = tbl_question_categories.category_id
INNER JOIN tbl_question_types ON tbl_questions.id = tbl_question_types.question_id
INNER JOIN tbl_types ON tbl_types.id = tbl_question_types.type_id
INNER JOIN tbl_question_institutions ON tbl_question_institutions.question_id = tbl_questions.id
INNER JOIN tbl_institutions ON tbl_institutions.id = tbl_question_institutions.institution_id
WHERE tbl_questions.id = 'c7aa15cb-27e5-4f28-9141-483f7cce8e56'
This is a select result

I want to add some space in my HTML output

I need some space between the RANK and STATE columns so that the information is not confusing, please do let me know: I am posting my query below,
CREATE VIEW IF NOT EXISTS LGBRANDRANK
AS
SELECT Brand_Name,Rank () Over (Order by Brand_Name) as BrandNameRank,
Vend_state as State, Strftime("%m",Inv_Date) as WeekNumber,StrfTime("%Y",Inv_Date) as YearOfSales, Sum(INV_Total) As WeeklyTotalSales from LGPRODUCT
inner join LGSUPPLIES on LGPRODUCT.Prod_SKU = LGSUPPLIES.Prod_SKU
inner join LGLINE on LGLINE.Prod_SKU = LGPRODUCT.Prod_SKU
inner join LGINVOICE on LGLINE.Inv_Num = LGINVOICE.Inv_Num
inner join LGVENDOR on LGSUPPLIES.Vend_ID = LGVENDOR.Vend_ID
inner join LGBRAND on LGBRAND.Brand_ID = LGPRODUCT.Brand_ID
group by Weeknumber, BRAND_NAME

Filter on two many to many relations

I'm trying to apply multiples filter on a table join to two tables
My tables
main
Id
Name
tags
Id
Name
main_primary_tags
mainId
tagId
main_secondary_tags
mainId
tagId
I want to select some items in main table which have some primary and secondary tags.
The difficulity is I need to have an exact result.
Exemple if I want to select items which have "Tag1 and "Tag2" tags, I want to have items which have both of these tags not just one of them (Like IN operator)
And I can filter on primary AND secondary..
Thanks for your help!
I would aggregate the tags into arrays and compare the arrays:
select main.id as main_id,
mt.tags as main_tags,
st.tags as secondary_tags
from main
left join lateral (
select array_agg(mpt.tag order by t.tag) as tags
from main_primary_tags mpt
join tags t1 on t1.id = mpt.tagid
where mpt.mainid = main.id
) mt on true
left join lateral (
select array_agg(mst.tag order by t.tag) as tags
from main_secondary_tags mst
join tags t2 on t2.id = mst.tagid
where mst.mainid = main.id
) st on true
where mt.tags = array['Tag1', 'Tag2']
and st.tags = array['Tag1', 'Tag2']
Note that the = operator for arrays depends on the order of the elements, so it's important to list them in the same way order by sorts them.
You can also do it like this
WITH tag_filter AS (
SELECT 'Tag1' AS primary_tag, 'Tag2' AS secondary_tag
UNION ALL
SELECT 'Tag1', 'Tag2'
)
SELECT m.*
FROM "main" m
INNER JOIN main_primary_tags mpt ON mpt.mainId = m.Id
INNER JOIN main_secondary_tags mst ON mst.mainId = m.Id
INNER JOIN tags primary_t ON primary_t.Id = mpt.tagId
INNER JOIN tags secondary_t ON secondary_t.Id = mst.tagId
INNER JOIN tag_filter tf
ON tf.primary_tag = primary_t."Name"
AND tf.secondary_tag = secondary_t."Name"
Or if you want something more compact in the tag_filter CTE
WITH tag_filter AS (
SELECT primary_tag, secondary_tag
FROM (VALUES ('Tag1', 'Tag2'), ('Tag1', 'Tag2')) t(primary_tag, secondary_tag)
)
SELECT m.*
FROM "main" m
INNER JOIN main_primary_tags mpt ON mpt.mainId = m.Id
INNER JOIN main_secondary_tags mst ON mst.mainId = m.Id
INNER JOIN tags primary_t ON primary_t.Id = mpt.tagId
INNER JOIN tags secondary_t ON secondary_t.Id = mst.tagId
INNER JOIN tag_filter tf
ON tf.primary_tag = primary_t."Name"
AND tf.secondary_tag = secondary_t."Name"
And in the case the tag_filter is much smaller than the main table, then you can also spool the tagId in the CTE, and then join with that instead.
WITH tag_name_filter AS (
SELECT primary_tag, secondary_tag
FROM (VALUES ('Tag1', 'Tag2'), ('Tag1', 'Tag2')) t(primary_tag, secondary_tag)
),
tag_filter AS (
SELECT primary_t.Id AS primary_tag_id, secondary_t.Id AS secondary_tag_id
FROM tag_name_filter tmf
INNER JOIN tags primary_t ON primary_t."Name" = tmf.primary_tag
INNER JOIN tags secondary_t ON secondary_t."Name" = tmf.secondary_tag
)
SELECT m.*
FROM "main" m
INNER JOIN main_primary_tags mpt ON mpt.mainId = m.Id
INNER JOIN main_secondary_tags mst ON mst.mainId = m.Id
INNER JOIN tag_filter tf
ON tf.primary_tag_id = mpt.tagId
AND tf.secondary_tag_id = mst.tagId

How to select multiple many to many in relation with a single table

I'm currently working with database, but I've got stuck with a select query.
However, I'm not database expert.
The query should return the data from a table that has two relationships of many to many.
This is my tables Diagram that would shows the concept of my question
The Select Query should View three columns, which are VidTbl.Name, ActorTbl.Name and SubTitelTbl.name.
So, I've read and search in the Internet and I've given tries
First try
SELECT
VidTbl.NAME AS Video_Titel_Name,
ActorTbl.NAME AS Actor_Name
FROM ActorInVid
INNER JOIN VidTbl
ON VidTbl.Id = ActorInVid.FKVidId
INNER JOIN ActorTbl
ON ActorTbl.Id = ActorInVid.FKActorId
UNION all
SELECT
VidTbl.NAME AS Video_Titel_Name,
SubTitelTbl.NAME AS SubTitel_Langu
FROM SubTitelInVid
INNER JOIN VidTbl
ON VidTbl.Id = SubTitelInVid.FKVidId
INNER JOIN SubTitelTbl
ON SubTitelTbl.Id = SubTitelInVid.FKSTId
The Result I've got, it was wrong
Then I tried another way to solve this problem, but again I've got another error
second try
SELECT Temp1.*
From (SELECT VidTbl.Id AS Video_Id,
VidTbl.NAME AS Video_Titel_Name,
ActorTbl.NAME AS Actor_Name
FROM ActorInVid
INNER JOIN VidTbl
ON VidTbl.Id = ActorInVid.FKVidId
INNER JOIN ActorTbl
ON ActorTbl.Id = ActorInVid.FKActorId) AS Temp1
SELECT Temp2.*
FROM (SELECT VidTbl.Id AS Video_Id,
SubTitelTbl.NAME AS SubTitel_Langu
FROM SubTitelInVid
INNER JOIN VidTbl
ON VidTbl.Id = SubTitelInVid.FKVidId
INNER JOIN SubTitelTbl
ON SubTitelTbl.Id = SubTitelInVid.FKSTId) AS Temp2
SELECT *
FROM VidTbl
INNER JOIN Temp1
on Temp1.Video_Id = VidTbl.Id
INNER JOIN Temp2
on Temp2.Video_Id = VidTbl.Id
The error, I've got in the last select that was wrong
Thanks a lot for your help any ways
I wish that my question is clear and useful
Thanks again.
You are close. This should work...
SELECT
VidTbl.Name,
ActorTbl.Name,
SubTitelTbl.name
FROM VidTbl
INNER JOIN ActorInVid ON VidTbl.Id = ActorInVid.FKVidId
INNER JOIN ActorTbl ON ActorTbl.Id = ActorInVid.FKActorId
INNER JOIN SubTitelInVid ON VidTbl.Id = SubTitelInVid.FKVidId
INNER JOIN SubTitelTbl ON SubTitelTbl.Id = SubTitelInVid.FKSTId
SELECT DISTINCT vt.Name, at.Name, st.Name
FROM VidTbl vt
JOIN ActionInVid aiv ON aiv.VidId = vt.Id
JOIN SubtitleInVid siv ON siv.VidId = vt.Id
JOIN ActorTbl at ON at.Id = aiv.ActorId
JOIN SubTitleTbl st ON st.Id = siv.STId

SQL rows dissapear when join added

SELECT tblArtworkTemplates.ID, tblArtworkTemplates.dateCreated, tblSpecifications.TxtPagination, tblSpecifications.FlatSizeW AS width,
tblSpecifications.FlatSizeL AS length, tblSpecifications.FlatSizeUOM AS uom,
(SELECT COUNT(1) AS Expr1
FROM tblArtworkUploads
WHERE (templateID = tblArtworkTemplates.ID)) AS uploadCount,
(SELECT COUNT(1) AS talks
FROM tblArtworkTemplateMessages
WHERE (templateID = tblArtworkTemplates.ID)) AS talkCount, tblArtworkTemplates.lastEditPing, tblUsers.userName AS Expr1
FROM tblUsers INNER JOIN
tblArtworkTemplates INNER JOIN
tblSpecifications ON tblArtworkTemplates.specID = tblSpecifications.id ON tblUsers.id = tblArtworkTemplates.editPingUserID
WHERE (tblArtworkTemplates.userID = 70)
The tblusers join is causing rows to disapear when tblArtworkTemplates.editPingUserID is null. Am I using the wrong sort of join type?
Maybe try a left outer join.. Or a Right outer join..
Wikipedia for informations about join
Try this, your join was wrong.
SELECT tblArtworkTemplates.ID, tblArtworkTemplates.dateCreated, tblSpecifications.TxtPagination, tblSpecifications.FlatSizeW AS width,
tblSpecifications.FlatSizeL AS length, tblSpecifications.FlatSizeUOM AS uom,
(SELECT COUNT(1) AS Expr1
FROM tblArtworkUploads
WHERE (templateID = tblArtworkTemplates.ID)) AS uploadCount,
(SELECT COUNT(1) AS talks
FROM tblArtworkTemplateMessages
WHERE (templateID = tblArtworkTemplates.ID)) AS talkCount, tblArtworkTemplates.lastEditPing, tblUsers.userName AS Expr1
FROM tblUsers u
INNER JOIN tblArtworkTemplates a ON u.id = a.editPingUserID
INNER JOIN tblSpecifications s ON a.specID = s.id ON
WHERE (a.userID = 70)
It depends on what you are after.
If you always want records from tblUsers, but data from Template+Specification only where data is available from both (in other words, if a Template doesn't have a Specification, you don't care about the Template), use this
FROM tblUsers
LEFT JOIN
tblArtworkTemplates
INNER JOIN tblSpecifications
ON tblArtworkTemplates.specID = tblSpecifications.id
ON tblUsers.id = tblArtworkTemplates.editPingUserID
If you always want records from tblUsers, but data from Template if available, and then from Specification if available (in other words, if a Template is available that has no Specification, get data from the Template record anyway), then use this
FROM tblUsers
LEFT JOIN
tblArtworkTemplates
LEFT JOIN tblSpecifications
ON tblArtworkTemplates.specID = tblSpecifications.id
ON tblUsers.id = tblArtworkTemplates.editPingUserID
or more commonly written (since the 2 left joins are commutative)
FROM tblUsers
LEFT JOIN tblArtworkTemplates
ON tblUsers.id = tblArtworkTemplates.editPingUserID
LEFT JOIN tblSpecifications
ON tblArtworkTemplates.specID = tblSpecifications.id