Joining 3 tables in SQL Server - sql

I have three tables namely: user, special_order, corp_order.
I want a result where it can display all orders placed by a user in both order tables.
My SQL statement is:
SELECT
u.user_id,
c.user_id,
s.user_id
FROM
corp_user u
JOIN
special_order s ON s.user_id = u.user_id
JOIN
corp_orders c ON c.user_id = u.user_id;
which is returning unnecessary data.

What you want is all orders, regardless of whether they are special orders or coprporate orders. Decide what columns you want from each corp_user table, and matching columns for orders from each order table and then do two separate queries that are linked by UNION ALL. (You want UNION ALL, not UNION because otherwise if there are exact matches in all fields, the duplicates would be eliminated.
Example for illustration:
SELECT
u.user_id,
s.order_id
FROM
corp_user u
INNER JOIN special_order s on u.user_id = s.user_id
UNION ALL
SELECT
u.user_id,
c.order_id
FROM
corp_user u
INNER JOIN corp_order c on u.user_id = c.user_id
Note: fields must match exactly - not necessarily in names, but in position. Names from first query will be used.

Related

Best approach for limiting rows coming back in SQL when joining for a sum

I need to get back a list of users and the total amount that they have ordered. In reality my query is more complex but I think this sums it up. My issue is, if a user made 5 orders for example, I'll get back their name and the total they've ordered 5 times due to the join (having 5 rows in the order table for that user).
What's the recommended approach for when you need to total the records in one table that has multiple rows without requiring many rows to come back? distinct could work but is this the best? (especially when my select chooses more information than what's below)
SELECT user.name, sum(order.amount) FROM USER user
INNER JOIN USER_ORDERS order
ON (user.user_id = order.user_id)
Are you just looking for GROUP BY?
SELECT u.name, SUM(o.amount)
FROM USER u JOIN
USER_ORDERS uo
ON u.user_id = uo.user_id
GROUP BY u.name, u.user_id;
Note that this has included user_id in the GROUP BY, just in case two users have the same name.
If you want all users, even those without orders, then you want a LEFT JOIN:
SELECT u.name, SUM(o.amount)
FROM USER u LEFT JOIN
USER_ORDERS uo
ON u.user_id = uo.user_id
GROUP BY u.name, u.user_id;
Or a correlated subquery:
SELECT u.name,
(SELECT SUM(o.amount)
FROM USER_ORDERS uo
WHERE u.user_id = uo.user_id
)
FROM USER u;
You could use the analytic version of SUM.
SELECT u.name, SUM(o.amount) OVER(PARTITION BY u.name)
FROM USER u JOIN
USER_ORDERS uo
ON u.user_id = uo.user_id;

1052: Column 'user_id' in field list is ambiguous when

I have 3 tables which share a user id, now I want to get data from all 3 but I don't know where I'm doing it wrong in this query
SELECT user_id, first_name, image_id, description, gender
FROM users a
JOIN user_services b ON b.user_id = a.user_id
JOIN user_timeframe c ON c.user_id = a.user_id
Two key best practices:
Always qualify all column references.
Use table aliases that are meaningful rather than arbitrary letters.
So:
SELECT u.user_id, u.first_name, ?.image_id, ?.description,
u.gender
FROM users u JOIN
user_services us
ON us.user_id = u.user_id JOIN
user_timeframe ut
ON ut.user_id = u.user_id;
The ? is because it is not clear what table those columns come from. (The other columns are guesses so they might not be right either.)
The preferred way should be explicit aliasing. There is another way to fix this query by using JOIN ... USING syntax:
SELECT user_id, first_name, image_id, description, gender
FROM users a
JOIN user_services b USING(user_id)
JOIN user_timeframe c USING(user_id);
db<>fiddle demo

How to rewrite this without duplication, using Standard SQL BIG Query syntax?

Merging two tables the time entries table onto the user's table. Currently using Big query standard SQL. The column id is supposed to have 1 unique id for each entry but yet it pulls multiple of the same id # My Question how to rewrite this query without receiving duplications in the results? How to use LEFT Join with UNION ALL or UNION DISTINCT?
--*** Gives Duplications for some reason ***
SELECT outer_e.hours, outer_e.id, outer_e.updated_at, outer_e.spent_date, u.first_name, u.is_active, u.id AS user_id, u.weekly_capacity FROM
(SELECT e.id, MAX(e.updated_at) AS updated_at FROM `harvest-experiment.harvest.time_entries` AS e
GROUP BY e.id LIMIT 1000) AS inner_e
LEFT JOIN `harvest-experiment.harvest.time_entries` AS outer_e
ON inner_e.id = outer_e.id AND inner_e.updated_at = outer_e.updated_at
LEFT JOIN `harvest-experiment.harvest.users` AS u
ON outer_e.user_id = u.id
I was missing the DISTANT Keyword next my SELECT keyword, by doing so seems to fix the duplication problem in the views.
__***** Current Solution *****———
--*** Returns a Left Joined Table of `time entries` and `users` ***
SELECT DISTINCT outer_e.hours, outer_e.id, outer_e.updated_at, outer_e.spent_date, outer_e.created_at, outer_e.client_id, u.is_admin, u.first_name, u.is_active, u.id AS user_id, u.weekly_capacity, client.name FROM
(SELECT e.id, MAX(e.updated_at) AS updated_at FROM `harvest-experiment.harvest.time_entries` AS e
GROUP BY e.id LIMIT 1000) AS inner_e
LEFT JOIN `harvest-experiment.harvest.time_entries` AS outer_e
ON inner_e.id = outer_e.id AND inner_e.updated_at = outer_e.updated_at
LEFT JOIN `harvest-experiment.harvest.users` AS u
ON outer_e.user_id = u.id

PostgreSQL: Get the count of rows in a join query

I am trying to get some data joining few tables. I have an audit table where I store the audits for actions performed by users. I am trying to get the list of users in the order of the number audits they have and the number of audits. I have the following query:
SELECT s.user_created,
u.first_name,
u.last_name,
u.email,
a.message as audits
FROM cbrain_school s
inner join ugrp_user u on s.user_created = u.user_id
inner join audit a on u.user_id = a.user_id
order by u.created_time desc;
This query will give me 1 row per entry in the audit table. I just want 1 row per user and the count of entries in the audit table ordered by the number of audits.
Is there any way to do that. I was getting an error when I tried to include count() in the above query
First of all you are joining with the table cbrain_school. Why? You are selecting no data from this table (except for s.user_created which is simply u.user_id). I suppose you want to limit the users show to the cbrain_school.user_created? Then use EXISTS or IN to look this up.
select u.user_id, u.first_name, u.last_name, u.email, a.message as audits
from ugrp_user u
inner join audit a on u.user_id = a.user_id
where u.user_id in (select user_created from cbrain_school)
order by u.created_time desc;
This shows much better that cbrain_school.user_created is mere criteria. (But the query result is the same, of course.) It's a good habit to avoid joins, when you are not really interested in the joined rows.
Now you don't want to show each message anymore, but merely count them per user. So rather then joining messages, you should join the message count:
select u.user_id, u.first_name, u.last_name, u.email, a.cnt
from ugrp_user u
inner join
(
select user_id, count(*) as cnt
from audit
group by user_id
) a on u.user_id = a.user_id
where u.user_id in (select user_created from cbrain_school)
order by u.created_time desc;
(You could also join all messages and only then aggregate, but I don't recommend this. It would work for this and many other queries, but is prone to errors when working with multiple tables, where you might suddenly count or add up values multifold. It's a good habit to join before aggregating.)

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