Problems with joins and a query - sql

Edit: Deleted my old message cause it was confusing. And i can't answer my own question for now.
Found, problem come from GROUP BY.
After some researches, i found that we can't use GROUP BY for group a column inside grouped rows.
So this work as expected :
SELECT candidats.*
, AVG(test_results.rate_good_answer) AS toto
FROM "candidats"
LEFT JOIN "sessiontests"
ON "sessiontests"."candidat_id" = "candidats"."id"
LEFT JOIN "test_results"
ON "test_results"."sessiontest_id" = "sessiontests"."id"
LEFT JOIN "questionnaires"
ON "questionnaires"."id" = "test_results"."questionnaire_id"
WHERE (sessiontests.terminate = 't' )
AND ("questionnaires"."category" LIKE '%java%' )
GROUP BY candidats.id
ORDER BY toto
But this will grouped only my column in test_results :
SELECT candidats.*,
FROM "candidats"
LEFT JOIN "sessiontests"
ON "sessiontests"."candidat_id" = "candidats"."id"
LEFT JOIN "test_results"
ON "test_results"."sessiontest_id" = "sessiontests"."id"
LEFT JOIN "questionnaires"
ON "questionnaires"."id" = "test_results"."questionnaire_id"
WHERE (sessiontests.terminate = 't' )
AND ("questionnaires"."category" LIKE '%java%' )
GROUP BY candidats.id, test_results.rate_good_answer
ORDER BY AVG(test_results.rate_good_answer)
Edit 3 :
My problem was the second query was returning each different test_results row for my candidats, whereas i expected it to return me one line per candidat.
First query, is the answer, and it works nice.

SELECT candidats.*
, AVG(test_results.rate_good_answer) AS toto
FROM "candidats"
LEFT JOIN "sessiontests"
ON "sessiontests"."candidat_id" = "candidats"."id"
LEFT JOIN "test_results"
ON "test_results"."sessiontest_id" = "sessiontests"."id"
LEFT JOIN "questionnaires"
ON "questionnaires"."id" = "test_results"."questionnaire_id"
WHERE (sessiontests.terminate = 't' )
AND ("questionnaires"."category" LIKE '%java%' )
GROUP BY candidats.id
ORDER BY toto

Related

SQL (snowflake) - how can I return 1 row from a join or use MAX in a second join from result of first

I have a large query that I have pasted parts of below.
I am wanting to use the result of the first join in my second join.
What I am trying to do get the last session that has a lead_conversion then I am getting all sessions in between then and the current row
This is the part I am struggling with
left join (
select ss.id, ss.session_start, ss.lead_id
from sessions ss
inner join lead_conversions inner_lc on inner_lc.session_id = ss.id
) prev_lc
on prev_lc.lead_id = lc.lead_id
and prev_lc.session_start::TIMESTAMP < s.session_start::TIMESTAMP
left join cte_sessions reset_prev_sess
on reset_prev_sess.lead_id = lc.lead_id
and reset_prev_sess.session_start::TIMESTAMP <= s.session_start::TIMESTAMP
and (
prev_lc.session_start::TIMESTAMP IS NULL
OR
reset_prev_sess.session_start::TIMESTAMP > prev_lc.session_start::TIMESTAMP
)
my issue is I cant just fetch the last prev_lc and I cant seem to use max(prev_lc.session_start)
I have tried grouping in first select and using max but this does not work as I believe this is ran before the on
left join (
select max(ss.session_start) as session_start, max(ss.lead_id) as lead_id
from sessions ss
inner join lead_conversions inner_lc on inner_lc.session_id = ss.id
group by inner_lc.id
) prev_lc on prev_lc.lead_id = lc.lead_id
I have also tried using max in the second join but this give the error
SQL compilation error: Invalid aggregate function in ON clause [MAX(CAST(PREV_LC.SESSION_START AS TIMESTAMP_NTZ(9)))]
left join cte_sessions reset_prev_sess
on reset_prev_sess.lead_id = lc.lead_id
and reset_prev_sess.session_start::TIMESTAMP <= s.session_start::TIMESTAMP
and (
prev_lc.session_start::TIMESTAMP IS NULL
OR
reset_prev_sess.session_start::TIMESTAMP > max(prev_lc.session_start::TIMESTAMP)
)
any help with this would be very appreciated
Thank you
if I understand correctly you are looking for to join with the last session start,so what you can do is to order by startsession in your subquery and limit to 1 record:
left join (
select ss.id, ss.session_start, ss.lead_id
from sessions ss
inner join lead_conversions inner_lc on inner_lc.session_id = ss.id
order by ss.session_start desc
limit 1
) prev_lc
the rest of query stays untouched.
So I have found a solution for this if any one comes across this. I ended up just rethinking how I go about it.
I ended up adding a row number for each conversion
with cte_sessions as (
select
s.id
,s.lead_id
,s.session_start::TIMESTAMP as session_start
,CASE WHEN MAX(lc.id) IS NOT NULL
then ROW_NUMBER() over (partition by s.lead_id, (CASE WHEN
MAX(lc.id) IS NOT NULL then 1 else 0 end)
order by s.session_start
)
END as conversion_row
from sessions s
left join lead_conversions lc on lc.session_id = s.id
group by s.id, s.session_start, s.lead_id, s.project_id, s.crawler_id
order by s.session_start
)
The I just did this in the join
left join cte_sessions prev_lc on prev_lc.lead_id = lc.lead_id and prev_lc.conversion_row = s.conversion_row - 1

Oracle compare query results with multiple joins against a table

I need to compare query results against a table. I have the following query.
select
i.person_id,
a.appellant_first_name,
a.appellant_middle_name,
a.appellant_last_name,
s.*
from CWLEGAL.individuals i inner join CWLEGAL.tblappealsdatarevisionone a
on i.casenm = a.D_N_NUMBER1 and
i.first_name = a.appellant_first_name and
i.last_name = a.appellant_last_name
inner join CWLEGAL.tblappealstosupremecourt s
on a.DATABASEIDNUMBER = s.DBIDNUMBER
order by orclid21;
I need to see what orclid21's in cwlegal.tblappealstosupremecourt don't appear in the above query.
I was able to get this to work.
select
i.person_id,
a.appellant_first_name,
a.appellant_middle_name,
a.appellant_last_name,
s.*
from CWLEGAL.tblappealstosupremecourt s
join CWLEGAL.tblappealsdatarevisionone a
on a.DATABASEIDNUMBER = s.DBIDNUMBER
left outer join CWLEGAL.individuals i on
i.casenm = a.D_N_NUMBER1 and
i.first_name = a.appellant_first_name and
i.last_name = a.appellant_last_name
where person_id is null
order by orclid21
You are making the first inner join between i and a, the result of which you're joining with s.
Now, if you want to see which records won't join, that's known as anti-join, and in whatever database you're querying it, it may be achieved by either selecting a null result or taking those records as a new result.
Examples, with taking your query (the whole code in the question) as q, assuming you've kept all the needed keys in it:
Example 1:
with your_query as q
select s.orclid21 from q
left join CWLEGAL.tblappealstosupremecourt s
on q.DATABASEIDNUMBER = s.DBIDNUMBER
and s.orclid21 is null
Example 2:
with your_query as q
select s.orclid21 from q
right join CWLEGAL.tblappealstosupremecourt s
on q.DATABASEIDNUMBER != s.DBIDNUMBER
Example 3:
with your_query as q
select s.orclid21 from CWLEGAL.tblappealstosupremecourt s
where s.DBIDNUMBER not in (select distinct q.DATABASEIDNUMBER from q)

Use name of controllers to find table name in Select

I want to extract a ID , User_ID value from one of the Companies and Contract tables, depending on the ContorollerName value.
select P.TitleProject, P.StartDateProject, P.EndDateProject,P.ControllerID,P.RecordID,P.IsAllocated,P.ProjectStatus_ID,
CN.ControllerName,CN.PersianName,
PU.ProjectID,PU.UserID,PU.RoleID,
CASE
WHEN CN.ControllerName = 'Company' THEN
Companies.Id,Companies.[User_Id]
WHEN CN.ControllerName = 'Contract' THEN
Contracts.Id,Contracts.[User_Id]
END
from Projects P
left outer join Controllers CN ON P.ControllerID = CN.Id
left outer join ProjectUsers PU ON P.Id = PU.ProjectID
where P.IsAllocated = 1
For example, if ContorollerName is 'Company' , the select command is as follows :
select P.TitleProject, P.StartDateProject, P.EndDateProject,P.ControllerID,P.RecordID,P.IsAllocated,P.ProjectStatus_ID,
CN.ControllerName,CN.PersianName,
PU.ProjectID,PU.UserID,PU.RoleID,
Companies.Id,Companies.[User_Id]
You are on the right track -- using left join. But you need to add the tables to the from clause with the appropriate logic.
The logic for the join is quite unclear. The query looks something like this:
select . . .,
coalesce(c.id, co.id) as id,
coalesce(c.user_id, co.user_id) as user_id
from Projects P left join
Controllers CN
on P.ControllerID = CN.Id left join
ProjectUsers PU
on P.Id = PU.ProjectID left join
companies c
on c.? = ? and -- no idea what the right join conditions are
c.ControllerName = 'Company' left join
contracts co
on co.? = ? and -- no idea what the right join conditions are
co.ControllerName = 'Contract'
where P.IsAllocated = 1

Postgresql select related tags (many to many)

I have a VIEW named review, which is related to a cars table, and the cars table have a many to many relationship with table tags (through join table named cars_tags), but what I need is retrieve the reviews from the cars which are related with some tags, AND at same time related to another tags. What I have today is the following SQL code:
SELECT "cars"."review".*
FROM "cars"."review"
LEFT JOIN cars.cars ON (cars.review.car_id = cars.cars.id)
LEFT JOIN cars.makes ON (cars.cars.make_id = cars.makes.id)
LEFT JOIN cars.cars_tags ON (cars.cars.id = cars.cars_tags.car_id)
LEFT JOIN cars.tags ON (cars.cars_tags.tag_id = cars.tags.id)
WHERE (cars.tags.id IN ('91782e95-8c5d-4254-82ab-b11a21306c18'))
AND (cars.tags.id IN ('031cec30-df27-471e-858d-53c3d9657c8a'))
ORDER BY "cars"."review"."score" DESC LIMIT 100
This SQL brings me NO results, but I am sure that there are cars which are related to first id:'91782e95-8c5d-4254-82ab-b11a21306c18'AND '031cec30-df27-471e-858d-53c3d9657c8a' at same time.
What am I doing wrong?
bool_or
select r.col1, r.col2
from
cars.review r
left join
cars.cars on r.car_id = cars.id
inner join
cars.cars_tags on cars.id = cars_tags.car_id
inner join
cars.tags on cars_tags.tag_id = tags.id
group by r.col1, r.col2
having
bool_or (tags.id = '91782e95-8c5d-4254-82ab-b11a21306c18')
and
bool_or (tags.id = '031cec30-df27-471e-858d-53c3d9657c8a')
order by r.score desc
limit 100
exists version:
select col1, col2
from cars.review
where exists (
select 1
from
cars.cars
inner join
cars.cars_tags on cars.id = cars_tags.car_id
inner join
cars.tags on cars_tags.tag_id = tags.id
where review.car_id = cars.id
group by 1
having
bool_or (tags.id = '91782e95-8c5d-4254-82ab-b11a21306c18')
and
bool_or (tags.id = '031cec30-df27-471e-858d-53c3d9657c8a')
)
order by score desc
limit 100
From what I understand you're interested in reviews for a car that has 2 specific tags.
This can be done with the query below. I've removed the reference to cars.make as you weren't retrieving any data from it. Also I've removed the reference to cars.tags as the only information you were using was the tag id which is in the cars_tags table.
SELECT "cars"."review".*
FROM "cars"."review"
WHERE
EXISTS (SELECT * FROM cars.cars_tags
WHERE cars.cars_tags.car_id = cars.review.cars_id
AND cars.cars_tags.tag_id = '91782e95-8c5d-4254-82ab-b11a21306c18')
AND
EXISTS (SELECT * FROM cars.cars_tags
WHERE cars.cars_tags.car_id = cars.review.cars_id
AND cars.cars_tags.tag_id = '9031cec30-df27-471e-858d-53c3d9657c8a')
ORDER BY "cars"."review"."score" DESC LIMIT 100
The query simply finds all reviews where there exists a cars_tags entry for the two tag_id's you're after.

Subquery with multiple joins involved

Still trying to get used to writing queries and I've ran into a problem.
Select count(region)
where (regionTable.A=1) in
(
select jxn.id, count(jxn.id) as counts, regionTable.A
from jxn inner join
V on jxn.id = V.id inner join
regionTable on v.regionID = regionTable.regionID
group by jxn.id, regionTable.A
)
The inner query gives an ID number in one column, the amount of times they appear in the table, and then a bit attribute if they are in region A. The outer query works but the error I get is incorrect syntax near the keyword IN. Of the inner query, I would like a number of how many of them are in region A
You must specify table name in query before where
Select count(region)
from table
where (regionTable.A=1) in
And you must choose one of them.
where regionTable.A = 1
or
where regionTable.A in (..)
Your query has several syntax errors. Based on your comments, I think there is no need for a subquery and you want this:
select jxn.id, count(jxn.id) as counts, regionTable.A
from jxn inner join
V on jxn.id = V.id inner join
regionTable on v.regionID = regionTable.regionID
where regionTable.A = 1
group by jxn.id, regionTable.A
which can be further simplified to:
select jxn.id, count(jxn.id) as counts
, 1 as A --- you can even omit this line
from jxn inner join
V on jxn.id = V.id inner join
regionTable on v.regionID = regionTable.regionID
where regionTable.A = 1
group by jxn.id
You are getting the error because of this line:
where (regionTable.A=1)
You cannot specify a condition in a where in clause, it should only be column name
Something like this may be what you want:
SELECT COUNT(*)
FROM
(
select jxn.id, count(jxn.id) as counts, regionTable.A
from
jxn inner join
V on jxn.id = V.id inner join
regionTable on v.regionID = regionTable.regionID
group by jxn.id, regionTable.A
) sq
WHERE sq.a = 1