how can i access column from subquery - sql

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')

Related

SQL convert "left join" with a "from" clause with multiple tables and a "where" condition

Image you have 2 tables like this:
User: with columns ID, NAME and APPARTMENT_ID.
Appartment: with columns ID, ADDRESS.
user.appartment_id is a foreign key for appartment.id.
With a left join I can do something like:
select u.name, a.address from user as u
left join appartment as a on u.appartment_id = a.id
And users with appartment_id null will match. If i write a select with this other structure (without using left join) those users won't match.
selct u.name, a.address from user as u, appartment as a
where u.appartment_id = a.id
Is there a way to modify the second query in order to obtain the same result set of the first, but without using left join?
Thanks
Without a left join you could just use this (assuming that the foreign key constraint has functioned correctly):
SELECT
u.name,
a.address
FROM user u
JOIN appartment a ON u.appartment_id = a.id
UNION
SELECT
name,
NULL AS address
FROM user
WHERE apartment_id IS NULL
;
But I'm curious as to why you'd want to do without a left join?
If you suspect that there there is incorrect data entered in user.apartment_id then you could use NOT EXISTS with a sub-query:
SELECT
u.name,
a.address
FROM user u
JOIN appartment a ON u.appartment_id = a.id
UNION
SELECT
name,
NULL AS address
FROM user
WHERE
NOT EXISTS (
SELECT 1
FROM appartment
WHERE appartment.id
= user.appartment_id)
);
This should cover you for null values and incorrect values.
If you are using Oracle, this is the old syntax for outer joins. You just need to add a (+) on the columns of the second table:
select u.name, a.address
from user as u, appartment as a
where u.appartment_id = a.id (+)
You will find this type of syntax a lot on Oracle environments, I guess that's why you asked it. You should probably use the new syntax though
Using left join is better, but here is an alternative.
select u.name, a.address
from user as u left join appartment as a on u.appartment_id = a.id
union
select name, null address
from user apartment_id is null

How to reference the same column from 2 seperate IDs SQL Server

I've been looking around for a bit unable to find an answer to this that works, So, I'm hoping someone can help me with my best bet to solve this. Basically I have a table with a User_id and a delegate_id, however both obviously reference the same user_mstr table. But what I want is the name of both the user and the delegate.
Here is the part of my query in question:
SELECT u.first_name, u.last_name, delegate_user_id, delegate_provider_ind,
tasks_ind, workflow_use_always_ind
FROM workflow_user_delegates ud
LEFT OUTER JOIN user_mstr u ON ud.user_id=u.user_id
But I want the delegate_id to be changed into a name, except obviously I already referenced user first and last name.
The exact software is SQL Server 2008. Thanks!
You can use alias = expression or expression AS alias to alias column names.
select
u.first_name
, u.last_name
, delegate_user_id
, delegate_first_name = d.first_name
, delegate_last_name = d.lastname
, delegate_provider_ind
, tasks_ind
, workflow_use_always_ind
from workflow_user_delegates ud
left join user_mstr u on ud.user_id = u.user_id
left join user_mstr d on ud.delegate_user_id = d.user_id
You need an additional LEFT JOIN:
SELECT u.first_name AS user_first_name, u.last_name AS user_last_name,
d.first_name AS delegate_first_name, d.last_name AS delegate_last_name,
delegate_user_id, delegate_provider_ind,
tasks_ind, workflow_use_always_ind
FROM workflow_user_delegates ud
LEFT OUTER JOIN user_mstr u ON ud.user_id=u.user_id
LEFT OUTER JOIN user_mstr d ON ud.delegate_user_id=d.user_id
You can join the same table twice, just provide different aliases for the table. Something like this:
....
FROM workflow_user_delegates ud
LEFT OUTER JOIN user_mstr u ON ud.user_id=u.user_id
LEFT OUTER JOIN user_mstr d ON ud.delegate_id=d.user_id
So any references to u.[...] in the SELECT will reference the one joined based on user_id, and any references to d.[...] will reference the one based on delegate_id.
To differentiate the columns in the SELECT clause, use a similar approach for aliasing. Something like this:
SELECT
....
u.first_name AS user_first_name,
u.last_name AS user_last_name,
d.first_name AS delegate_first_name,
d.last_name AS delegate_last_name,
....

sql - How to have multiple select/from statements in one query

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

Include null/0 rows in a group by

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

SQL: Matching multiple columns value

I have a database set up so that the username (username) and id (id) are stored in the members table.
I have another table that records reports and I record each column in the table (fid), who reported it (rid) and who they were reporting (id) which both match to the user's id in the members table.
How could I get a query to pull the username for both the rid and id?
My current query is
SELECT selfreport.fid, selfreport.rid,
selfreport.id, members.username as username
FROM members, selfreport
WHERE members.id = selfreport.id
ORDER BY fid
but this only gets the username for who they were reporting. How can I get it to pull the username for both?
You need to join to your members table twice. Try something like this:
SELECT selfreport.fid,
selfreport.rid,
selfreport.id,
COALESCE(WhoReported.username, 'Not Specified') AS WhoReportedUN,
COALESCE(ReportedTo.username, 'Not Specified') AS ReportedToUN
FROM selfreport
LEFT JOIN members WhoReported ON WhoReported.id = selfreport.id
LEFT JOIN members ReportedTo ON ReportedTo.id = selfreport.rid
ORDER BY fid
Do not use implicit SQL '89 joins they are an antipattern.
Use explicit join syntax instead.
SELECT s.fid, s.rid, s.id, m1.username as username, m2.username as rusername
FROM selfreport S
INNER JOIN members m1 ON (m1.id = s.id)
INNER JOIN members m2 ON (m2.id = s.rid)
ORDER BY s.fid
If id or rid is optional, use a left join.
SELECT
s.fid, s.rid, s.id
, COALESCE(m1.username, 'nobody') as username
, COALESCE(m2.username, 'nobody') as rusername
FROM selfreport S
LEFT JOIN members m1 ON (m1.id = s.id)
LEFT JOIN members m2 ON (m2.id = s.rid)
ORDER BY s.fid
You need to join members twice:
SELECT selfreport.fid,
selfreport.rid,
selfreport.id,
m1.username AS ReportToUsername,
m2.username AS ReporteeUsername
FROM selfreport
INNER JOIN members m1
ON m1.id = selfreport.id
INNER JOIN members m2
ON m2.id = selfreport.rid
ORDER BY fid
Since you were doing an implicit join in your original query, I believe INNER JOIN will suit you well. However, if it's possible to have null values in selfreport.id or selfreport.rid, you should use LEFT JOIN instead.