SQL inner join with max function by groub - mysql

I have some problem from using the inner join with group by using max function.
my detail :
Table inventory
site_ID tank_number volume times-tramp ID
1 1 5000 06/08/2017 15:00 1
1 1 4900 06/08/2017 15:01 2
1 2 6000 06/08/2017 15:05 3
1 3 4000 06/08/2017 15:05 4
2 1 3000 06/08/2017 15:33 5
2 2 2000 06/08/2017 15:34 6
1 1 4800 06/08/2017 15:36 7
1 2 5800 06/08/2017 16:00 8
Table wp_users (wordpress)
ID Name
1 aaa
2 bbbb
Now, I using with wpdatatable plugin in wordpress so i want use the inner join and group with tank_number and using data update by times-strap
The result should be is :
When user "aaa" login then ID will is 1
the result that want to show.
site_ID tank_number volume times-tramp
1 1 4800 06/08/2017 15:36
1 2 5800 06/08/2017 16:00
1 3 4000 06/08/2017 15:05
But
I got the this result :
site_ID tank_number volume times-tramp
1 1 5000 06/08/2017 15:00
1 2 6000 06/08/2017 15:05
1 3 4000 06/08/2017 15:05
So can every one help to advise me so I have show my code the showing the error due to i can't join with 2 table by correct syntax sql.
this code can work without inner join
select site_id, tank_product, volume, timestramp from inventory as t1
inner join (
select tank_product as tank, max(timestramp) as time from inventory
where site_id=1 group by tank_product) as t2
on t1.tank_product = t2.tank and t1.timestramp = t2.time and t1.site_id=1
and Now I trying to using with inner join but not work now.
SELECT inventory.site_id,
inventory.tank_product,
inventory.volume,
inventory.timestramp,
wp_users.ID
FROM inventory as t1
INNER JOIN wp_users
(SELECT inventory.tank_product, max(inventory.timestramp) as time from inventory
WHERE inventory.site_id=wp_users.ID GROUP BY inventory.tank_product) as t2
ON t1.inventory.tank_product=t2.tank AND t1.inventory.timestramp=t2.time AND t1.inventory.site_id=wp_users.ID
Can advise me for correct way to use the inner join by group by max function.

So, the schema you present and the queries you provided don't line up (naming is all over the place). It would be very helpful if you provided a sql fiddle to help present your problem (at least in the future).
In any event, I think you were close:
select t2.site_id, t2.tank_product, t1.volume, t2.time
from (
select site_id, tank_product, max(timestramp) as time
from inventory
group by site_id,tank_product) t2
inner join inventory t1
on t2.site_id=t1.site_id and t1.tank_product=t2.tank_product and t2.time=t1.timestramp
inner join wp_users u
on u.id=t2.site_id
where u.id=1
order by t2.site_id,t2.tank_product asc
(Assuming you pass the wp_users.id into the query; I've hard-coded that with u.id=1.)
fiddle

Try to run this:
SELECT i1.site_ID, i1.tank_product, i1.volume, i.timestramp, iu.User_ID
FROM Inventory AS i1
INNER JOIN (
SELECT u.ID AS UserID, i.tank_product, MAX (i.timestramp) AS time
FROM Inventory AS i2
INNER JOIN wp_users AS u
ON i2.site_id = u.ID
GROUP BY u.ID, i.tank_product
) as iu
ON i1.tank_product = iu.tank_product
AND i1.timestramp = iu.time
AND i1.site_ID = iu.UserID;

Related

SQL Inner Join only one row based on filtered records

I have the following tables
user
id
name
1
John
2
Jack
3
George
essay
id
date_submitted
user_id
project_id
1
2020-12-10
1
1
2
2020-05-01
2
2
3
2020-04-10
3
2
project_phase
id
project_id
date
phase
1
1
2020-01-01
early
2
1
2020-05-31
mid
3
1
2020-11-30
late
4
2
2020-01-01
early
5
2
2020-03-31
mid
6
2
2020-04-30
late
1 User submits only 1 essay in one project
and I want to have a combined table which shows me the user and the phase at which the essay was submitted.
I'm trying to get the record with the MAX date from project_phase that is below the date_submitted
So using the above data I want to get
user
date_submitted
phase
John
2020-12-10
late
Jack
2020-05-01
late
George
2020-04-10
mid
so far I combined the tables with INNER JOIN but the following query returns duplicate records. I also tried ROW_NUMBER() and MAX() but I didn't structure it correctly to get the answer I'm looking for
SELECT
U.name,
E.date_submitted,
P.phase
FROM
essay E
INNER JOIN user U ON U.id = E.user_id
INNER JOIN project_phase P ON P.project_id = E.project_id and E.date <= P.date_submitted
Any help appreciated, thanks.
I would suggest a correlated subquery:
SELECT U.name, E.date_submitted,
(SELECT P.phase
FROM project_phase P
WHERE P.project_id = E.project_id AND
P.date <= E.date_submitted
ORDER BY p.date DESC
LIMIT 1
) as phase
FROM essay E JOIN
user U
ON U.id = E.user_id;

Mysql join not showing all records

I am using Php with join, I have two tables ("services" and "service_detail"), I want to get all services
but want to know which service selected or notselected by vendor
Here is my services table strcture
id service_name image
1 Abc abc.jpg
2 xyz xyz.jpg
3 OPS ops.jpg
4 tys tys.jpg
5 byp byp.jpg
Here is my services_detail table strcutre
id vendor_id service_id price
1 101 1 50
2 101 2 70
3 101 3 80
4 101 4 30
5 102 1 70
6 102 2 40
...
I tried with following query but showing only selected services, but i want to get all services with parameter ( selected or notselected)
Where i am wrong ? Here is my query
SELECT sd.vendor_id, sd.service_id, sd.price, s.service_name, s.image
FROM services_detail sd
LEFT JOIN services s
ON sd.service_id = s.id
WHERE sd.vendor_id = '101'
Move your where clause to be AND in ON clause:
AND sd.vendor_id = '101'
And interchange tables in join to get all servcies
SELECT sd.vendor_id, sd.service_id, sd.price, s.service_name, s.image,
IF (sd.vendor_id is not null, 'Opted', 'Not opted') as status
FROM services s
LEFT JOIN services_detail sd
ON sd.service_id = s.id AND sd.vendor_id = '101';
In simple words, when there is a where clause including filters on table of Left Join then it will act like INNER JOIN not LEFT JOIN.

How to display only the rows where number of unique values in one column equals value in second column

(Using mysql 5.0)
I have this table:
opportunity main_user_id certificate_id required_certificates
1 491 1 2
1 341 1 2
1 161 1 2
1 161 2 2
1 205 2 2
1 578 2 2
2 161 2 2
2 466 3 2
2 466 2 2
2 156 2 2
2 668 2 2
3 222 5 1
3 123 5 1
3 875 5 1
3 348 5 1
I need to only display the rows where number of distinct values in certificate_id equals value in required_certificates.
opportunity_id column has id's from 0 to 15 and main_user_id's repeat (hence I can't use group by)
The table is basically a list of users matched for particular job opportunity, who have the required certificates. All i need to do now, is to only show the ones who have both of the required certificates, not one OR another.
My current sql statement:
select op_main.id as opportunity_id, u.id as main_user_id, c.id as certificate_id, required2.required as required_certificates
from opportunities as op_main
join opportunity_certificates as oc on oc.opportunity_id = op_main.id
join certificates as c on c.id = oc.certificate_id and oc.is_required
join user_certificates as uc on uc.certificate_id = c.id
join users as u on u.id = uc.user_id
join (
select id as op_id, (
select count(distinct c.id)
from opportunities as op
join opportunity_certificates as oc on oc.opportunity_id = op.id
join certificates as c on c.id = oc.certificate_id and oc.is_required
join user_certificates as uc on uc.certificate_id = c.id
join users as u on u.id = uc.user_id
where uc.certificate_id = oc.certificate_id and oc.is_required and op.id = op_id
) as required from opportunities
) as required2 on required2.op_id = op_main.id
where uc.certificate_id = oc.certificate_id and oc.is_required and op_id = op_main.id
based on the table above the output would be:
opportunity main_user_id
1 161
2 466
3 222
3 123
3 875
3 348
I spent many hours trying to work it out. If someone is keen on helping me, I can send you the database. Thanks.
It is quite simple with windowed functions - MySQL 8 and above:
WITH cte AS (
SELECT *, COUNT(DISTINCT certificate_id) OVER(PARTITION BY user_id) AS cnt
FROM (
-- your query with joins
) sub
)
SELECT *
FROM cte
WHERE cnt = required_certificates;
DBFiddle Demo
It turns out that MySQL 8.0 doesn't support COUNT(DISTINCT ...) OVER so I used subquery with DISTINCT.
ER_NOT_SUPPORTED_YET: This version of MySQL doesn't yet support '(DISTINCT ..)'

SQL select from tables

I've got tables:
Table1= USER_ID ITEM_ID
1 12
1 13
2 12
3 12
3 1
3 2
etc..
And second table:
Products = ITEM_ID PRICE
1 1.3
2 0.1
4 22
12 33
13 45
It is just example. How can I get ID's of clients who paid more than average order value?
I tried many times, but I always get errors.
You can do a JOIN between the tables and comparing the average price with specific user price paid like
select t1.user_id
from table1 t1
join products p on t1.item_id = p.item_id
group by t1.user_id
having p.price > avg(p.price);

How to join 3 table with this condition?

I have 3 tables: product, customer and transaction.
Product:
id_product price
1 1000
2 2000
Customer:
id_customer name
1 Tom
2 Jack
Transaction:
id_transaction id_product id_customer qty date
1 1 1 10 2013-02-21
2 2 1 50 2013-02-21
3 1 2 15 2013-02-21
I want to achieve this result:
id_customer name total_transaction purchase_qty subtotal
1 Tom 2 60 110000
2 Jack 1 15 15000
How I can get that result using a query in MySQL?
SELECT t.id_customer, c.name,
COUNT(t.id_customer) AS total_transaction,
SUM(t.qty) as purchase_qty
FROM transaction t
INNER JOIN customer c
ON t.id_customer = c.id_customer
GROUP BY t.id_customer,c.name
SELECT cs.id_customer, cs.name, COUNT(tr.transaction) AS total_transaction, SUM(tr.qty) as purchase_qty, SUM(tr.qty*pr.prize)
FROM customer AS cs
LEFT JOIN transaction AS tr ON tr.id_customer = cs.id_customer
LEFT JOIN product AS pr ON pr.id_product = tr.id_product
GROUP BY cs.id_customer
I suppose you are a total beginner, so I did this for you. Next time, if you have ANY own ideas, give to us, so we don't have to write the whole query for you. Show some effort.
SELECT c.id_customer, c.name, count(t.id_transaction) AS total_transaction
FORM Customer c INNER JOIN Transaction T
ON C.id_customer = T.id_customer
GROUP BY c.id_customer
You need a group by statement since you want to aggregate results for a given customer :
SELECT id_customer, name, count(id_transaction) AS total_transaction
FORM Customer, Transaction
WHERE Transaction.id_customer = Customer.id_customer
GROUP BY id_customer
This does not solve your whole problem, but you've got the idea.