MySQL - Need help to figure out multiple joins - sql

I am using the following query to get the transactions from a table made to and from a user. I then want to retrieve the username for the sender_id and for the recipient_id. However I can only seem to get it for the recipient_id or the sender_id. Anyone have any ideas how I can get both.
SELECT us.name, ta.amount, ta.recipient_id, ta.sender_id, ta.timestamp_insert
FROM `transactions` AS ta
JOIN users AS us
ON ta.recipient_id=us.u_id
WHERE ta.sender_id =111111 OR ta.recipient_id = 111111
LIMIT 0 , 10
Transactions Table Columns:
transaction_id
tw_id
tw
sender_id
recipient_id
amount
timestamp_insert
timestamp_start
timestamp_complete
transaction_status
User Table Columns:
u_id,
name

You need to join twice, thus:
SELECT ta.amount, ta.recipient_id, ta.sender_id, ta.timestamp_insert, sender.name as Sender, recipient.name as Recipient
FROM `transactions` AS ta
JOIN users AS recipient
ON ta.recipient_id=recipient.u_id
JOIN users AS sender
ON ta.sender_id=sender.u_id
WHERE ta.sender_id =111111 OR ta.recipient_id = 111111
LIMIT 0 , 10

Related

INNER JOIN of pagevies, contacts and companies - duplicated entries

In short: 3 table inner join duplicates records
I have data in BigQuery in 3 tables:
Pageviews with columns:
timestamp
user_id
title
path
Contacts with columns:
website_user_id
email
company_id
Companies with columns:
id
name
I want to display all recorded pageviews and, if user and/or company is known, display this data next to pageview.
First, I join contact and pageviews data (SQL is generated by Metabase business intelligence tool):
SELECT
`analytics.pageviews`.`timestamp` AS `timestamp`,
`analytics.pageviews`.`title` AS `title`,
`analytics.pageviews`.`path` AS `path`,
`Contacts`.`email` AS `email`
FROM `analytics.pageviews`
INNER JOIN `analytics.contacts` `Contacts` ON `analytics.pageviews`.`user_id` = `Contacts`.`website_user_id`
ORDER BY `timestamp` DESC
It works as expected and I can see pageviews attributed to known contacts.
Next, I'd like to show pageviews of contacts with known company and which company is this:
SELECT
`analytics.pageviews`.`timestamp` AS `timestamp`,
`analytics.pageviews`.`title` AS `title`,
`analytics.pageviews`.`path` AS `path`,
`Contacts`.`email` AS `email`,
`Companies`.`name` AS `name`
FROM `analytics.pageviews`
INNER JOIN `analytics.contacts` `Contacts` ON `analytics.pageviews`.`user_id` = `Contacts`.`website_user_id`
INNER JOIN `analytics.companies` `Companies` ON `Contacts`.`company_id` = `Companies`.`id`
ORDER BY `timestamp` DESC
With this query I would expect to see only pageviews where associated contact AND company are known (just another column for company name). The problem is, I get duplicate rows for every pageview (sometimes 5, sometimes 20 identical rows).
I want to avoid selecting DISTINCT timestamps because it can lead to excluding valid pageviews from different users but with identical timestamp.
How to approach this?
Your description sounds like you have duplciates in companies. This is easy to test for:
select c.id, count(*)
from `analytics.companies` c
group by c.id
having count(*) >= 2;
You can get the details using window functions:
select c.*
from (select c.*, count(*) over (partition by c.id) as cnt
from `analytics.companies` c
) c
where cnt >= 2
order by cnt desc, id;

Ignore duplicate data id in SQL Query?

How do I ignore duplicate data ids from query SQL results:
In this case I tried to combine several tables. Like this scheme that I made:
Transactions
----------------------------------------------------------------------------------------
id
user_id
type
amount
invoice_transaction (Relation to invoice)
created_at
updated_at
Users
----------------------------------------------------------------------------------------
id
name
email
phone
birth
address
picture
created_at
updated_at
Vouchers
----------------------------------------------------------------------------------------
id
code
amount
type
created_at
updated_at
Vouchers Transactions
----------------------------------------------------------------------------------------
id
user_id
voucher_id
created_at
updated_at
invoice
----------------------------------------------------------------------------------------
id
order_data
payment_id
last_total
status
created_at
updated_at
Payment
----------------------------------------------------------------------------------------
id
name
tax
created_at
updated_at
This is a query I made.
SELECT t.id, t.user_id, u1.name, u1.email, v.code, t.amount, t.type, t.created_at, t.invoice_transaction, i.status, p.name,
FROM transactions AS t
INNER JOIN users AS u1 on u1.id = t.user_id
LEFT JOIN vouchers_transaction AS vt on vt.user_id = u1.id
LEFT JOIN vouchers AS v on v.id = vt.voucher_id
LEFT JOIN invoice AS i on i.order_data = t.invoice_transaction
LEFT JOIN payment AS p on p.id = i.payment_id
WHERE t.type = 'buy'
ORDER BY id ASC
In this case I managed to get the data I wanted. But the results of the query contained duplicate transaction id data such as:
Result
---------------------------------------------------------------------------------------------------------------------------
id user_id name email code amount type invoice_transaction status payment_name
1 1 John Doe John#mail.com ycqs1 150 buy SCS11DAS success bank
1 1 John Doe John#mail.com ycqs1 150 buy SCS11DAS success bank
2 1 John Doe John#mail.com n1ksa 200 buy SCS12DAS success bank
Update
It seems like this happened because in the transaction voucher table there is no connection with the transaction table.
Example:
Voucher Transaction
---------------------------------------------------------------------------------------------------------------------------
id user_id voucher_id
1 1 1
2 1 2
3 2 3
Then each transaction will duplicate according to the number of vouchers used in the transaction vouchers, both transactions that use vouchers or not.
I know the best way is to change the database schema. But in this case can it still be done in this case or not?
Results
Result
---------------------------------------------------------------------------------------------------------------------------
id user_id name email code amount type invoice_transaction status payment_name
1 1 John Doe John#mail.com ycqs1 150 buy SCS11DAS success bank
1 1 John Doe John#mail.com sa31a 150 buy SCS11DAS success bank
2 1 John Doe John#mail.com n1ksa 200 buy SCS12DAS success bank
How do I ignore the duplicated transaction id?
Try using group by
SELECT t.id, t.user_id, u1.name, u1.email, v.code, t.amount, t.type, t.created_at, t.invoice_transaction, i.status, p.name,
FROM transactions AS t
INNER JOIN users AS u1 on u1.id = t.user_id
LEFT JOIN vouchers_transaction AS vt on vt.user_id = u1.id
LEFT JOIN vouchers AS v on v.id = vt.voucher_id
LEFT JOIN invoice AS i on i.order_data = t.invoice_transaction
LEFT JOIN payment AS p on p.id = i.payment_id
WHERE t.type = 'buy'
GROUP BY SELECT t.id, t.user_id, u1.name, u1.email, v.code, t.amount, t.type, t.created_at, t.invoice_transaction, i.status, p.name
ORDER BY id ASC
You will always get double ID's because the rows are different. The code and amount columns are all unique and you havent told SQL what to do with those columns. The group by Mahesh showed will work, if you change it to resolve the difference in the code and amount columns.
what amount do you want to see for ID 1? The lowest? highest? average? sum?.
either you have to remove those 2 columns from the query, or provide an aggregate function to resolve what to show
SELECT DISTINCT ON column1, column2, ...
FROM table_name;
The SELECT DISTINCT ON statement is used to return only distinct (different) values.

How to Left Join SQL Subquery with Table

Goal: Create a query that calculates the ratio of ids that have/don't have a particular attribute.
Table 1: events
Fields: event_id, event_name, user_id
Field event_id is unique key/index
Field event_name has 3 potential values, one of which is the one being inspected.
Field user_id is a foreign key from Table 2
Table 2: users
Fields: id (and a long list of other attributes that aren't pertinent)
To get the list of user_ids with the qualifying attribute, I created the following:
SELECT DISTINCT events.user_id AS viewing_ids
FROM events
WHERE event_name = 'view_user_profile'
As I would expect this provides the list of users that have the corresponding event_name associated with their user_id
The next part is where I'm getting mixed up. Yes, I could COUNT(DISTINCT the select to get the count ids that have the attribute 'view_user_profile' but that only provides half the answer. What I need to do is then Join that list with the full user_id list from the table users and then determine when the id exists or doesn't.
I'm thinking the initial SELECT needs to be
SELECT
(CASE WHEN viewers IS NULL THEN false
ELSE true END) AS has_viewed_profile
, COUNT(user_id) AS users
FROM
(SELECT DISTINCT events.user_id AS viewing_ids
FROM events
WHERE event_name = 'view_user_profile') viewers
LEFT JOIN
users
ON
??? = users.id
This is where I get lost, I don't have a column name for viewers...
I think this is what you want:
select count(e.user_id) / count(*) as view_ratio
from users u left join
(select distinct e.user_id
from events e
where e.event_name = 'view_user_profile'
) e
on e.user_id = u.id;

SQL Query With Join for 2 Tables

I'm unable to form a query with the following tables, which will find out all the Notes from Note table, which is created by any user, who belongs to the logged in user's same company.
Note:
note_id (int),
note_text (varchar),
created_by (int)
User:
user_id (int),
company_id (int)
Logged in user's user id is passed as parameter to the query.
I want to pick up notes from the table Notes where created_by in (user_id of all users whose company_id = company_id of LOGGED_IN_USER)
Please help me to formulate out the query. Looks pretty straight forward, but just can't reach to it's end.
I'm not sure if LOGGED_IN_USER is a table or another object, but if it is a table with the columns you referenced, a join like this would work.
select note_text
from Note n
JOIN User u ON u.user_id = n.created_by
JOIN LOGGED_IN_USER lin ON lin.user_id = u.user_id
and lin.company_id = u.company_id
u might need a Foreign Key for user_id to Notes. and use INNER JOIN
Thanks Vinnie and all for your responses. I finally succeeded to figure out the query. LOGGED_IN_USER_ID is just a numeric parameter which should be passed to the query.
select n.* from Note n where
n.created_by in (
select u1.user_id from User u1 inner join User u2
on u1.company_id=u2.company_id and u2.user_id = :LOGGED_IN_USER_ID*
)
Thanks again.
If i am not misunderstood your question,Try this way
SELECT note_text
FROM Note n
INNER JOIN User u ON u.user_id = n.created_by
WHERE n.created_by= (select u.user_id from User where company_id=LOGGED_IN_USER LIMIT 1 )

Select by frequency

I have two tables, like that:
users(id, name)
phones(user_id, number)
I'd like to select all user's names that are in more than three rows in the table phones. How can I do that?
Join the tables and add a having clause that limits the results returned by the count of the user_ids
select name,
count(user_id)
from users u
join phones p
on u.id = p.user_id
group by name
having count(user_id) > 3
SQL Fiddle: http://sqlfiddle.com/#!2/c5516/2
select name from user
join phones on id = user_id
Group By user_id
Having Count(number) > 3