Basic join and aggregate? - sql

I have table A, table B and table C.
I want to select 2 fields from table A, one field from table B (an inner join between these two I'm assuming) and the Count for each record where the identifier on table B is found on table C.
So I'll have:
OpeartiveId | OperativeNumber | JobLocation | CountOfJobIdInWorkTable
Edit:
Operative
OperativeId
OperativeNumber
Jobs
JobId
JobLocation
Work
JobId
OperativeId

Assuming you also want records from a and b that have no matching records in c, you'll need an outer join:
select a.pk_a, b.pk_b, count(c.pk_c)
from a
inner join b on a.pk_a = b.pk_a
left outer join c on b.pk_b = c.pk_b
group by a.pk_a, b.pk_b;

Translate this to your actual schema and try it:
select a.one, a.two, b.three, count(c.id)
from a
join b on a.id=b.id
left join c on c.bid=b.id
group by a.one, a.two, b.three, b.id

Not sure if this is what you looking for. looking at the filed you provided i came up with this.
select o.operativeId, o.OperativeNumber, j.JobLocation, COUNT(w.jobId)
from dbo.Operative o
Inner join works w
ON o.OperativeID = w.OperativeId
INNER JOIN jobs j
ON w.jobId = j.jobId
GROUP by o.operativeId, o.OperativeNumber, j.JobLocation

select a.a,a.b,b.a,(select count(*) from c where c.b_id = b.id)
from a
join b on a.b_id = b.id

Related

SQL: Multiple joins on multiple tables where some column values are not mandatory

I am trying to join multiple tables where the values in columns e.Email, e.Phone are voluntary. I would like to select all rows even if e.Email, e.Phone contain empty values.
Currently, I am only able to select rows where e.Email, e.Phone values are present.
SELECT a.ID_1
,b.Tier
,e.Email
,e.Phone
FROM CustomerActivity a
JOIN CustomerSummary b
ON a.ID_1 = b.ID_1
JOIN DimensionCustomer c
ON b.ID_1 = c.ID_1
JOIN LegacyCustomerMapping d
ON c.ID_2 = d.ID_2
JOIN LegacyCustomerContactData e
d.ID_3 = e.ID_3
Many thanks for any kind of advice!
I would recommend using left join instead of join in your query. That should get the results you are looking for.
Image from: https://www.w3schools.com/sql/sql_join.asp
This can be obtained by using a LEFT OUTER JOIN for the table containing the Email and Phone fields:
SELECT a.ID_1, b.Tier, e.Email ,e.Phone
FROM CustomerActivity a
JOIN CustomerSummary b ON a.ID_1 = b.ID_1
JOIN DimensionCustomer c ON b.ID_1 = c.ID_1
JOIN LegacyCustomerMapping d ON c.ID_2 = d.ID_2
LEFT OUTER JOIN LegacyCustomerContactData e d.ID_3 = e.ID_3
Using an OUTER JOIN avoids records not being returned when there are no related rows in the joined table. Note that OUTER is optional and might not be supported by all databases.

ERROR: invalid reference to FROM-clause entry for table "oth"

I have a problem with this query
SELECT DISTINCT(oth.book) FROM book_meta_keywords oth,
(SELECT bmk.meta_keyword AS metaKeyword, bmk.book AS book FROM books b
INNER JOIN customers_books cvb ON cvb.book = b.id
INNER JOIN book_meta_keywords bmk ON bmk.book = b.id
WHERE cvb.customer = 1 ) AS allCustomerPurchasedBooksMeta
INNER JOIN books b ON b.id = oth.book
WHERE oth.meta_keyword = allCustomerPurchasedBooksMeta.metaKeyword AND oth.book != allCustomerPurchasedBooksMeta.book AND b.status = 'GOOD'
I am getting below error for this query.
ERROR: invalid reference to FROM-clause entry for table "oth"
LINE 6: INNER JOIN books b ON b.id = oth.book
^
HINT: There is an entry for table "oth", but it cannot be referenced from this part of the query.
, Time: 0.002000s
But if I run the below query it works
SELECT DISTINCT(oth.book) FROM book_meta_keywords oth,
(SELECT bmk.meta_keyword AS metaKeyword, bmk.book AS book FROM books b
INNER JOIN customers_books cvb ON cvb.book = b.id
INNER JOIN book_meta_keywords bmk ON bmk.book = b.id
WHERE cvb.customer = 1 ) AS allCustomerPurchasedBooksMeta
WHERE oth.meta_keyword = allCustomerPurchasedBooksMeta.metaKeyword AND oth.book != allCustomerPurchasedBooksMeta.book
Can anyone help me why... query is basically trying to get similar books based on purchased books based on their meta keywords.
thanks.
This is your FROM clause:
FROM
book_meta_keywords oth,
(SELECT ... FROM ... WHERE ...) AS allCustomerPurchasedBooksMeta
INNER JOIN books b ON b.id = oth.book
You are mixing explicit and implicit joins (the latter is denoted by the comma). Don't. They have different prescendence rules and the query planner ends up evaluating the the second condiiton before oth was seen.
As for how to solve this: assuming that the logic is indeed what you want, that's a lateral join:
FROM
book_meta_keywords oth
CROSS JOIN LATERAL (SELECT ... FROM ... WHERE ...) AS allCustomerPurchasedBooksMeta
INNER JOIN books b ON b.id = oth.book
I suspect, however, that your query could be further simplified. You might want to ask another question for this, explaning the purpose of the query and providing a minimum reproducible example.
You are missing join
SELECT DISTINCT oth.book FROM book_meta_keywords oth join
(SELECT bmk.meta_keyword AS metaKeyword, bmk.book AS book FROM books b
INNER JOIN customers_books cvb ON cvb.book = b.id
INNER JOIN book_meta_keywords bmk ON bmk.book = b.id
WHERE cvb.customer = 1 ) AS allCustomerPurchasedBooksMeta
on oth.meta_keyword = allCustomerPurchasedBooksMeta.metaKeyword and
oth.book != allCustomerPurchasedBooksMeta.book
INNER JOIN books b ON b.id = oth.book
WHERE b.status = 'GOOD'
Well it can work :
SELECT DISTINCT oth.book
FROM book_meta_keywords oth
INNER JOIN books b ON b.id = oth.book
, (SELECT bmk.meta_keyword AS metaKeyword, bmk.book AS book
FROM books b
INNER JOIN customers_books cvb ON cvb.book = b.id
INNER JOIN book_meta_keywords bmk ON bmk.book = b.id
WHERE cvb.customer = 1 ) AS allCustomerPurchasedBooksMeta
WHERE oth.meta_keyword = allCustomerPurchasedBooksMeta.metaKeyword
AND oth.book != allCustomerPurchasedBooksMeta.book
AND b.status = 'GOOD'
But does this do what you need...

Need to join but on a secondary table

I have this one view all_people_expanded_view that has all the data needed except 1.
The race of client is in race table. But the description is in race_info. I need to join on race on people_id, but really need then to join race on race_info on column race_info_id and then get description. I am stuck on how to make this connection.
select a.full_name, a.dob, a.gender, a.ethnicity, c.race_info_id
from all_people_expanded_view a inner join
race c
on a.people_id = c.people_id
this would be fine but it only has race_info_id and not the description which is in the race_info_id table.
Is this what you're looking for?
select
a.full_name,
a.dob,
a.gender,
a.ethnicity,
c.race_info_id,
ri.description
from
all_people_expanded_view a
inner join
race c
on a.people_id = c.people_id
left join --Maybe an inner join, depending on your data
race_info ri
on ri.race_info_id = c.race_info_id
select
a.full_name, a.dob, a.gender, a.ethnicity, c.race_info_id , ri.description
from
all_people_expanded_view a
inner join race c on a.people_id = c.people_id
inner join race_info ri on ri.race_info_id = c.race_info_id

How to count the like

I want to count many likes i have for specific post in my database I had create this simple Query show How many Like I have for one resource"post" but when I add to main script it miss it up
SELECT COUNT(Likes.resourceID) AS Count_resID, Resources.Id
FROM Likes INNER JOIN
Resources ON Likes.resourceID = Resources.Id
GROUP BY Resources.Id
Result
Count_resID Id
----------- -----------
1 53
2 54
2 60
2 61
1 62
(5 row(s) affected)
SELECT a.Id, a.summary, a.pageId, a.name, a.createdOn, COUNT(Likes.resourceID) AS Count_resID
FROM Resources AS a INNER JOIN
Topics_Resources AS b ON a.Id = b.ResourceID INNER JOIN
Skills_Resources AS c ON a.Id = c.ResourceID INNER JOIN
Types AS d ON a.typeId = d.Id INNER JOIN
Modules AS m ON a.ModuleId = m.ModuleID INNER JOIN
ContentItems AS ci ON m.ModuleID = ci.ModuleID INNER JOIN
Tabs AS t ON t.TabID = ci.TabID INNER JOIN
TabModules AS tb ON t.TabID = tb.TabID INNER JOIN
Likes ON a.Id = Likes.resourceID LEFT OUTER JOIN
HtmlText AS h ON tb.ModuleID = h.ModuleID
GROUP BY a.Id, a.summary, a.pageId, a.name, a.createdOn
Id summary pageId name createdOn Count_resID
----------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------
53 jihuih http://localhost/ideapark/testpage99.aspx jklhjk 2013-05-10 07:24:21.833 12
54 1 http://localhost/ideapark/testpage33.aspx sdvs 2013-05-09 07:24:21.833 2
60 sdvsdv http://localhost/ideapark/tesCreatedate.aspx dsvsdv 2013-05-13 07:32:13.133 8
61 newtest http://localhost/ideapark/newtest.aspx newTest 2013-05-13 10:35:08.027 2
62 sdvsdvds http://localhost/ideapark/page21.aspx svdsvs 2013-05-14 14:06:15.603 35
(5 row(s) affected)
The problem is that you are joining multiple tables, and more than one of these tables has a 1-n relationship. You are getting Cartesian products where you don't expect it.
The right way to fix this is to do subqueries to summarize before you join.
You do, however, have a quick-and-easy fix using count(distinct). Use this select statement instead:
SELECT a.Id, a.summary, a.pageId, a.name, a.createdOn,
COUNT(distinct Likes.Id) AS Count_resID;
This assumes that each record in likes has an id to uniquely identify it.
A better way to fix it (especially if this query will be re-used) involves changing the from joins from:
TabModules AS tb ON t.TabID = tb.TabID INNER JOIN
Likes ON a.Id = Likes.resourceID LEFT OUTER JOIN
To something like:
. . .
TabModules AS tb ON t.TabID = tb.TabID INNER JOIN
(select l.resourceId, count(*) as NumLikes
from Likes l
) l ON a.Id = l.resourceID LEFT OUTER JOIN
. . .
And then referencing NumLikes in the select clause.
Based off of your results change there is an issue with one of the criteria you are using to join your tables. You must make sure Tables in join all have one to one ratio with the base table.

Left Join Yielding no results

I'm coming across an issue where when I write a query as so:
SELECT a.v, b.w, c.x, d.y, e.z
FROM a
JOIN b
on a.id = b.id
LEFT JOIN c
on a.id = c.id
LEFT JOIN d
on b.code=d.code
JOIN e
on a.n = e.n
WHERE
a.zone = 10
WITH (nolock)
I get several hundred results, but when I modify it to this:
SELECT a.v, b.w, c.x, d.y, e.z
FROM a
JOIN b
on a.id = b.id
LEFT JOIN c
on a.id = c.id AND c.n = 0
LEFT JOIN d
on b.code=d.code AND d.n = 0
JOIN e
on a.n = e.n
WHERE
a.zone = 10
WITH (nolock)
I get zero results.
From my understanding of SQL and left joins, I feel that getting any results with the first query means I should definitely get at least one result with the second, if only one where fields from c and d are null. Does PROGRESS implement outer joins in an unusual manner?
You might want to figure out what the c.n and d.n values are. Try something like this to figure out where your starting point is.
SELECT c.n, d.n, count(*)
FROM a
JOIN b
on a.id = b.id
LEFT JOIN c
on a.id = c.id
LEFT JOIN d
on b.code=d.code
JOIN e
on a.n = e.n
WHERE
a.zone = 10
group by c.n, d.n
Then you can adjust your query based on the result