I'm trying to pull a report where each column is selecting from a specific table set. However, one of the columns needs to pull from a completely different table set and still be included in the same report. Of course, this doesn't work:
select u.first_name, ticket_work.time_spent
FROM tickets LEFT OUTER JOIN ticket_work ON ticket_work.ticket_id = tickets.id JOIN users u
(select count(tickets.id) FROM tickets JOIN users u)
where tickets.assigned_to = u.id
...
So just the part (select count(tickets.id) FROM tickets JOIN users u) needs to be selecting from the different table set but still be included in the report.
I'm a little confused by your question. Are you wanting to return the user, the count of tickets for that user, and the amount of time spent overall? If so, something like this should work:
select u.id, u.first_name,
SUM(tw.time_spent) summed_time_spent,
COUNT(DISTINCT t.id) count_tickets
FROM users u
LEFT JOIN tickets t
ON u.id = t.assigned_to
LEFT JOIN ticket_work tw
ON tw.ticket_id = t.id
GROUP BY u.id, u.first_name
Your questions is unclear, but just generally, it sounds like you're trying to join to a derived table (i.e., a query). In that case, do this:
SELECT...
FROM...
table_A A LEFT JOIN
(SELECT keyfield, valuefield FROM table_b WHERE ...) B
ON A.keyfield = B.keyfield
Does that make sense? To make a derived table, you put a query inside of parenthesis, give it an alias ('B' in this case), and then join it to your other tables as though it were a regular table.
Don't know about your table structure but you may use a sub query for such requirement
select u.first_name, ticket_work.time_spent,(select count(tickets.id) FROM tickets where ticket.id=ticket_work.ticket_id) as myCount
FROM tickets LEFT OUTER JOIN ticket_work ON ticket_work.ticket_id = tickets.id JOIN users u
where tickets.assigned_to = u.id
Related
select u.phone, u.email , t.to_address (error from this)
from user_accounts u
where u.id
in
(select w.user_id
from wallets w
where w.id
in
(
select t.wallet_id
from withdraws t
where t.to_address
in
('1F6o1fZZ7', 'pJDtRRnyhDN')))
I want to get the column to_address from subquery. How can I get it in postgresql?
I try assign 'AS' for subquery but it didn't work
A join returns a result table constructed from data from multiple tables. You can also retrieve the same result table using a sub query. A sub query is simply a SELECT statement within another select statement.
select u.phone, u.email , t.to_address (
from user_accounts u
INNER JOIN wallets w ON u.id= w.user_id
INNER JOIN withdraws t ON t.wallet_id =w.id
where t.to_address in ('1F6o1fZZ7', 'pJDtRRnyhDN')
use join with all the table, you dont need any subquery
select u.phone, u.email , ww.to_address
from user_accounts u left join wallets w on u.id=w.user_id
left jon withdraws ww on w.id=ww.wallet_id
where ww.to_address in ('1F6o1fZZ7', 'pJDtRRnyhDN')
You can not access t.address because that column inside in condition.
I used left join but it seems it will be inner join type because you used filter in ('1F6o1fZZ7', 'pJDtRRnyhDN') though after applying where condition it also behave like inner join
You cannot achieve what you're trying using subquery. When you want records from different tables and they have a unique column in common that connects them then You should do it using a JOIN.
Sometimes (Not all cases) IN can cause performance problems, so you should consider knowing more about different types of JOINS(https://www.w3schools.com/sql/sql_join.asp)
Check the link for comparison:
Inner join versus doing a where in clause
About the Query:
SELECT
u.phone, u.email , t.to_address (error from this)
FROM
user_accounts u
INNER JOIN wallets w ON u.id = w.id
INNER JOIN withdraws t ON t.wallet_id = w.id
WHERE
t.to_address IN ('1F6o1fZZ7', 'pJDtRRnyhDN')
SELECT * FROM student_mentor sm INNER JOIN users u
ON sm.student_id = u.user_id
WHERE sm.teacher_id = $teacher_id
Teacher_id being the session id,
I want to see all the students that have the same mentor.
Right now if I run this I just see all of the students twice, maybe one of you knows why?
My db scheme
You are not specifying on which columns you want to do the join, so you're getting a cross reference where all records are joined to all records.
You should do something like (not sure about your column names):
SELECT * FROM student_mentor sm INNER JOIN users u
ON sm.student_id = u.user_id
WHERE sm.teacher_id = $teacher_id
I have three tables: Comments, Users and CommentsHelpfulness.
Users can submit several comments, which are stored in the Comments table.
CommentsHelpfulness has three columns: UserID, CommentID and a "Helpful" Boolean. Every user can indicate for every comment if they find it useful, which will create an entry in the CommentsHelpfulness table.
I want a query that gives me all Comment IDs, with the name of the user that submitted it and shows whether the currently logged in user found it helpful, did not find it helpful or did not say anything about it. So the ID of a comment the current user did not express his opinion about should still be output, just without the helpful Boolean.
To me that sounds like it should be done like this using a left join:
SELECT Comments.ID, Users.Nom, CommentsHelpfulness.Helpful
FROM (Comments INNER JOIN Users
ON Comments.UserID = Users.ID)
LEFT JOIN CommentsHelpfulness
ON (CommentsHelpfulness.CommentID = Comments.ID
AND (CommentsHelpfulness.UserID = ?))
Unfortunately this does not output Comment IDs without an entry in the CommentsHelpfulness table. Why does this not work? Is it because of Access?
I think the issue is the inner join, not the left join.
Try removing that table:
SELECT c.ID, ch.Helpful
FROM Comments as c LEFT JOIN
CommentsHelpfulness as ch
ON ch.CommentID = c.ID AND
ch.UserID = ?
select c.id, c.Nom, d.Helpful from (
select a.ID, b.Nom from Comments a left join Users b
on a.UserID = b.ID) c left join CommentsHelpfulness d
on d.CommentID = c.ID;
I want to query a database for users and the the amount of time they spent on each Activity Category. These categories are stored in the table ActivityCategory (int Id, varchar Name). There's only 8 of them and I want to see all of them, even when nobody spent time on a specific category.
I have the following query:
select u.NoEmploye, u.FirstName, u.LastName, Total=sum(h.NbHeures), ac.Name
from Users u
join Semaines s on u.EntityGuid=s.UserGuid
join HeuresProjets hp on s.Id=hp.WeekId
join Heures h on hp.HPId=h.HpGuid
join ActivityCodes code on h.Code=code.ActivityId
join ActivityCategory ac on code.Categorie=ac.Id
group by u.NoEmploye, u.FirstName, u.LastName, ac.Name
order by u.NoEmploye
It works fine but it doesn't return unused ActivityCategories. I tried every combination of full/left/right/inner/outer/you-name-it joins. The best I could get is completely null rows when a category is used by nobody and a null ac.Name for categories a specific user doesn't use but others do. I suspect the group by [...]ac.Name part is what's "eating" the unused categories. What am I doing wrong? Should I write a select query the a second one to group the results? I'll have a dozen more similar queries to write so I'd like to understand instead of just having a fixed query with no explanation.
EDIT
Lamak's second query works so far but it has the same problem when I add a where clause.
EDIT2 ypercube' edit works perfectly
Now let's see if I understand the query correctly.
I coalesce the Sum with 0 to have a proprer value when the result would be null. I start the selection from ActivityCategory to make sure I have all of them, even the unused ones, which I cross join with users to have every combination of ActivityCategory and Users. I left join Activitycodes to only get relevant rows and then I inner join my other tables to get to Semaine. My condition are applied to the Semaine table's join because I want to filter my data before the cross join. Finally, I group my data by Users and ActivityCategory to have the sum works.
This should do:
SELECT u.NoEmploye, u.FirstName, u.LastName, Total=sum(h.NbHeures), ac.Name
FROM ActivityCategory ac
LEFT JOIN ActivityCodes code
ON code.Categorie=ac.Id
LEFT JOIN Heures h
ON h.Code=code.ActivityId
LEFT JOIN HeuresProjets hp
ON hp.HPId=h.HpGuid
LEFT JOIN Semaines s
ON s.Id=hp.WeekId
LEFT JOIN Users u
ON u.EntityGuid=s.UserGuid
GROUP BY u.NoEmploye, u.FirstName, u.LastName, ac.Name
ORDER BY u.NoEmploye
Basically, if you want all Categories, you need to use that table as the first table on your FROM and do LEFT JOINs to that table.
UPDATE
If you want every category for every user on your results, you'll need a CROSS JOIN:
SELECT u.NoEmploye, u.FirstName, u.LastName, Total=sum(h.NbHeures), ac.Name
FROM ActivityCategory ac
CROSS JOIN Users u
LEFT JOIN ActivityCodes code
ON code.Categorie=ac.Id
LEFT JOIN Heures h
ON h.Code=code.ActivityId
LEFT JOIN HeuresProjets hp
ON hp.HPId=h.HpGuid
LEFT JOIN Semaines s
ON s.Id=hp.WeekId AND u.EntityGuid=s.UserGuid
GROUP BY u.NoEmploye, u.FirstName, u.LastName, ac.Name
ORDER BY u.NoEmploye
To solve the issue when you want to add a WHERE clause:
SELECT u.NoEmploye, u.FirstName, u.LastName,
Total=COALESCE(SUM(h.NbHeures),0), ac.Name
FROM ActivityCategory ac
CROSS JOIN Users u
LEFT JOIN
ActivityCodes code
JOIN Heures h
ON h.Code=code.ActivityId
JOIN HeuresProjets hp
ON hp.HPId=h.HpGuid
JOIN Semaines s
ON s.Id=hp.WeekId
AND (some condition on the dates) -- add here
ON ac.Id = code.Categorie
AND u.EntityGuid = s.UserGuid
GROUP BY u.NoEmploye, u.FirstName, u.LastName, ac.Name
ORDER BY u.NoEmploye
I have a table called USERS that has a foreign key to the table GROUPS (a user can pertain to one or none GROUPS). The table USERS also contains a column ISDELETED (a char column with T or F).
I need a query to retrieve all the GROUPS and all the USERS that are not deleted, if all the users in a GROUP are deleted or no users are defined I need the query to return NULL for that GROUP.
I tried with the following query:
SELECT GROUPS.*, USERS.*
FROM GROUPS INNER JOIN
USERS ON GROUPS.ID = USERS.GROUPID
WHERE USERS.ISDELETED = 'F'
But this query does not returns the groups that are empty. SQL and me are not the best friends in world, some help will be great, thanks.
If you want all the groups, regardless of a match in the users table, you should use a left outer join:
SELECT GROUPS.*, USERS.*
FROM GROUPS
LEFT OUTER JOIN
USERS
ON GROUPS.ID = USERS.GROUPID AND USERS.ISDELETED = 'F'
You should just need to do a left outer join -
SELECT GROUPS.*, USERS.*
FROM GROUPS LEFT OUTER JOIN
USERS ON GROUPS.ID = USERS.GROUPID
WHERE USERS.ISDELETED = 'F'
Here's a reference I like to use to remind myself of the differences in sql joins.
You need to use the LEFT OUTER JOIN operator instead of the INNER JOIN.