MySQL JOIN Multiple Tables With LIMIT Last Table By DateTime per result - mysql

I got an interesting one. I have 3 tables I am joining. The last table I joined, I want to only see the latest entry by date and not double up my results with the same user and just have different login times.
Example (this is a sample table only):
SELECT a.user_id
a.user_name,
b.department,
c.last_logon_date_time,
c.computer_name
FROM table1 a
LEFT OUTER JOIN table2 b ON a.user_id = b.user_id
LEFT OUTER JOIN table3 c ON c.user_id = c.user_id
Below will give me the results I am looking for but looks very inefficient and is really slow. Any way of speeding this up and making it more efficent?
I could do this
SELECT a.user_id
a.user_name,
b.department,
(SELECT c.last_logon_datetime FROM table 3 c WHERE a.user_id = c.user_id ORDER BY c.last_logon_datetime DESC LIMIT 1) as last_logon_datetime,
(SELECT c.computer_name FROM table 3 c WHERE a.user_id = c.user_id ORDER BY c.last_logon_datetime DESC LIMIT 1) as computer_name
FROM table1 a
LEFT OUTER JOIN table2 b ON a.user_id = b.user_id
Thank You.

You can JOIN to a "table" created from a subselect like this:
SELECT t1.user_id, t1.user_name, t2.department, t3.computer_name, t3.logon_date
FROM table1 AS t1
LEFT OUTER JOIN table2 AS t2 ON t1.user_id = t2.user_id
LEFT OUTER JOIN
(SELECT user_id, computer_name, MAX(last_logon_date) AS `logon_date` FROM table 3 GROUP BY computer_name) AS t3 ON t1.user_id = t3.user_id

Related

Group by Use Query if SQL LEFT JOIN is performed multiple times

I think it's impossible, but I'm asking if there's a good way.
There are A table / B table / C table.
The table was joined LEFT JOIN based on table A with FK called id of each table.
At this time, I would like to output the count(*) as B table rows and C table rows based on b.id(B_CNT) c.id(C_CNT)
SELECT
*
FROM
A
LEFT JOIN B ON A.ID = B.ID
LEFT JOIN C ON A.ID = C.ID (base query)
how could I count group by b.id and c.id?
You could try:
SELECT
COUNT(DISTINCT B.ID), COUNT(DISTINCT C.ID)
FROM A
LEFT JOIN B
ON A.ID = B.ID
LEFT JOIN C
ON A.ID = C.ID
(I couldn't quite understand from your question, but I'm making an assumption that you want the distinct count of "ID" from each table)
You can use a couple of scalar subqueries. For example:
select id,
(select count(*) from b where b.id = a.id) as b,
(select count(*) from c where c.id = a.id) as c
from a

Join 4 Tables to find total and sort by total

i have 3 tables
1) users
2) user_likes
3) user_pictures
4) user_pucture_likes
users(id, name)
user_likes(id, user_id, like)
user_pictures(id, user_id, filename)
user_picture_likes(id, user_picture_id, like)
what i am trying to do is to sort the user on the total like on user_like + user_picture_like
I am not good with joining more than 2 tables.
i got upto here
SELECT t2.user_id, sum(t1.total_likes) as image_likes from user_pictures as t2 JOIN (
SELECT sum(like_status) as total_likes, user_picture_id FROM `user_picture_likes` GROUP BY user_picture_id ORDER BY total_likes DESC
)as t1
ON t1.user_picture_id = t2.id GROUP BY t2.user_id ORDER BY image_likes DESC
and how do i proceed from here?
Try this
SELECT T1.Id AS UserID, SUM(T2.like), Tmp.filename AS Image, Tmp.Imageslikes
FROM users T1
LEFT JOIN user_likes T2 ON T1.Id = T2.user_id
LEFT JOIN (
SELECT T3.user_id, T3.filename, SUM(T4.likes) Imageslikes
FROM user_pictures LEFT JOIN user_picture_likes T4 ON T3.Id = T4.user_picture_id
GROUP BY T3.user_id, T3.filename
)Tmp ON T1.Id = Tmp.user_id

MySQL How to do a 3 table join

I'm trying to perform a 3 table join on MySQL in order to achieve something like the diagram below.
The main problem I'm having is that I only want to work with the records of table A which has 100 records so if there are no relationships for the right tables I would like to see a null.
This all works fine when only table A and B are involved but when I try to do the third join with C I'm getting more than the original 100 records, I'm getting 130 which I believe is because is adding the records that match B-C with duplicate data from table A.
What am I missing?
This is the SQL I currently have that returns correctly 100 records
SELECT count(A.id)
FROM tableA A
LEFT JOIN TableB B ON B.id = A.b_id
This is what I'm trying to do that is returning more than the original 100 records for Table A.
SELECT count(A.id)
FROM tableA A
LEFT JOIN TableB B ON B.id = A.b_id
LEFT JOIN TableC C ON C.id = B.c_id
This could be resolved by a JOIN to a subquery rather than a table.
If you had unique Ids to join to, it would simply be like you've tried already (arbitrary example):
SELECT * from table1 t1
LEFT JOIN table2 t2 on t2.id = t1.id
LEFT JOIN table3 t3 on t3.id = t2.id
If, however the id field in table3 wasn't unique, you'd get multiple rows for each duplicate. You could resolve this by:
SELECT * from table1 t1
LEFT JOIN table2 t2 on t2.id = t1.id
LEFT JOIN (SELECT * FROM table3 GROUP BY id) t3 on t3.id = t2.id
So, using your example (assuming only the third join has duplicates), something like:
SELECT count(A.id)
FROM tableA A
LEFT JOIN TableB B ON B.id = A.b_id
LEFT JOIN (SELECT * FROM TableC GROUP BY id) C ON C.id = B.c_id
...should do the trick. This is down to assumption of your table and data structure, so you might want to make the asterisk more explicit.
SELECT count(distinct A.id)
FROM tableA A
LEFT JOIN TableB B ON B.id = A.b_id
LEFT JOIN TableC C ON C.id = B.c_id

MySQL - Joining table on itself based on criteria from other table

Here’s the problem I am trying to solve:
Table1 has Product ID’s, dates, and prices for those dates, Table2 has Product attributes.
I want to be able to compare prices for a client for different products on the same date based on a set of attributes. I’m easily able to get a list of products/dates/prices for a ‘simple’ product, as well as an ‘advanced’ product (see below).
I want to be able to join these two tables such that the output looks like:
[CLIENT] [PRODUCT] [DATE] [SIM_PROD] [SIM_PRICE] [ADV_PROD] [ADV_PRICE]
Here is as far as I've made it
SELECT b.NAME AS ‘CLIENT’, a.NAME AS ‘SIMPLE_PRODUCT’, t1.DATE AS ‘DATE’, t1.PIVOT_PRICE AS ‘SIMPLE_PRICE’
FROM TABLE1 t1
LEFT JOIN PRODUCT a
ON t1.PRODUCT_ID = a_PRODUCT_ID
LEFT JOIN CLIENTS b
ON a.PARTNER_ID = b.PARTNER_ID
WHERE a.CRITERIA = TRUE;
SELECT b.NAME AS ‘CLIENT’, a.NAME AS ‘ADV_PRODUCT’, t2.DATE AS ‘DATE’, t2.PIVOT_PRICE AS ‘ADV_PRICE’
FROM TABLE1 t2
LEFT JOIN PRODUCT a
ON t2.PRODUCT_ID = a_PRODUCT_ID
LEFT JOIN CLIENTS b
ON a.PARTNER_ID = b.PARTNER_ID
WHERE a.CRITERIA = FALSE;
I've been able to build similar tables where I pull in price from TABLE1 labeling it as t1 then pull in price again from TABLE1 and labeling it as t2, but only when using criteria in TABLE1, not criteria in a table that needs to be joined.
Is it possible to 'set' a table (EG simple) then 'set' a second one (EG advanced) and then join them on PARTNER_ID and DATE?
You can join the two subqueries:
SELECT t1.client, t1.date, t1.simple_product, t1.simple_price, t2.adv_product, t2.adv_price
FROM (
SELECT b.NAME AS CLIENT, a.NAME AS SIMPLE_PRODUCT, t1.DATE, t1.PIVOT_PRICE AS SIMPLE_PRICE
FROM TABLE1 t1
LEFT JOIN PRODUCT a
ON t1.PRODUCT_ID = a_PRODUCT_ID
LEFT JOIN CLIENTS b
ON a.PARTNER_ID = b.PARTNER_ID
WHERE a.CRITERIA = TRUE
) AS t1
JOIN (
SELECT b.NAME AS CLIENT, a.NAME AS SIMPLE_PRODUCT, t1.DATE, t1.PIVOT_PRICE AS SIMPLE_PRICE
FROM TABLE1 t1
LEFT JOIN PRODUCT a
ON t1.PRODUCT_ID = a_PRODUCT_ID
LEFT JOIN CLIENTS b
ON a.PARTNER_ID = b.PARTNER_ID
WHERE a.CRITERIA = FALSE
) AS t2
ON t1.client = t2.client AND t1.date = t2.date
You'll probably need to select additional criteria and add them to the ON condition. Otherwise this will produce a full cross product between all the products that have the same client and date.
Your desired output has an additional PRODUCT column, but I couldn't see where that comes from.

select from 2 tables with for statement in sql

i have 2 table and want to select data from them
table 1 :
id
name
table 2
id
name
table1.id
and i want a query to make this resualt:
table1.id
table1.name
count(table2.id)
this is simple and solved by this way :
SELECT
c.id as corridor_id,
c.name as corridor_name,
(SELECT COUNT( r.id ) FROM rooms AS r WHERE r.corridorid = c.id ) as room_count
FROM corridors AS c
now if i add another table like this :
table3
id
name
table2.id
and want a query like this :
table1.id
table1.name
count(table2.id)
count(table3.id)
idk how can i do such as this query, but if there is a way i'll be happy to find it, many tnx
You'll want to join them all together, and then Group them along these lines:
SELECT
t1.Id,
t1.Name,
Count(t2.Id) AS T2Count,
Count(t3.Id) AS T3Count
FROM table1 t1
JOIN table2 t2
ON t1.Id = t2.table1_id
JOIN table3 t3
ON t2.id = t3.table2_id
GROUP BY t1.Id, t1.Name
You don't need nested SELECT statement here. You can do it by grouping and to avoid double-counting you would want DISTINCT keyword:
SELECT
c.id as corridor_id,
c.name as corridor_name,
COUNT(DISTINCT r1.id),
COUNT(DISTINCT r2.id)
FROM
corridors c
JOIN rooms r ON r.corridorid = c.id
JOIN rooms2 r2 ON r2.corridorid = c.id
GROUP BY c.id
If you want to properly treat missing values (0 counts) you can also do this:
SELECT
c.id as corridor_id,
c.name as corridor_name,
IFNULL(COUNT(DISTINCT r1.id), 0),
IFNULL(COUNT(DISTINCT r2.id), 0)
FROM
corridors c
LEFT JOIN rooms r ON r.corridorid = c.id
LEFT JOIN rooms2 r2 ON r2.corridorid = c.id
GROUP BY c.id