How to resolve the below nested JOIN function error - ms-access

Base Data:
-----------------------
Date | ID | PL |
-----------------------
16.09.2019| 21 | 0 |
17.09.2019| 21 | 0 |
18.09.2019| 21 | 1 |
19.09.2019| 21 | 2 |
Expected Output:
-----------------------------------
Date | ID | PL | ZC | TC |
-----------------------------------
16.09.2019| 21 | 0 | 2 | 4 |
17.09.2019| 21 | 0 | 2 | 4 |
18.09.2019| 21 | 1 | 2 | 4 |
19.09.2019| 21 | 2 | 2 | 4 |
Code is working with single JOIN function but not with the below code
SELECT [4G].*,Z.ZC,T.TC
FROM 4G
LEFT JOIN (SELECT COUNT([4G].[ID]) AS ZC, [4G].[ID]
FROM 4G
WHERE [4G].[PL] =0
GROUP BY [4G].[ID])
AS Z
ON [4G].[ID] = Z.[ID]
LEFT JOIN (SELECT COUNT([4G].[ID]) AS TC, [4G].[ID]
FROM 4G
GROUP BY [4G].[ID])
AS T
ON [4G].[ID] = T.[ID];
ERROR Shown is:
"Syntax Error(missing operator) in query expression
'[4G].[ID] = Z.[ID]
LEFT JOIN (SELECT COUNT([4G].[ID]) AS TC, [4G].[ID]
FROM 4G
GROUP BY [4G].[ID])
AS T
ON [4G].[ID] = T.[ID]'

Access requires parentheses for each pair of joined tables before another join:
SELECT [4G].*,Z.ZC,T.TC
FROM ([4G]
LEFT JOIN (
SELECT COUNT([4G].[ID]) AS ZC, [4G].[ID]
FROM [4G]
WHERE [4G].[PL] =0
GROUP BY [4G].[ID]
) AS Z ON [4G].[ID] = Z.[ID])
LEFT JOIN (
SELECT COUNT([4G].[ID]) AS TC, [4G].[ID]
FROM [4G]
GROUP BY [4G].[ID]
) AS T ON [4G].[ID] = T.[ID];
Results:
Date ID PL ZC TC
16/9/2019 21 0 2 4
17/9/2019 21 0 2 4
18/9/2019 21 1 2 4
19/9/2019 21 2 2 4

Related

MySQL select N latest rows for each product from 3 relational tables

Now i have this code which return latest record for each product. But i don't know how to modify this to get for example 3 latest rows for each product.
I want to compare latest product prices and i need few latest rows of each.
shops
id | shopId
-----------
1 | 2345
2 | 6573
products
id | shopId | title | active | pDateAdded | pDateUpdate
---------------------------------------------------------------------------
18 | 1 | Honda | 1 | 2021-03-07 01:56:34 | 2021-03-07 04:36:34
19 | 2 | Subaru | 1 | 2021-03-07 03:43:34 | 2021-03-08 04:36:34
20 | 1 | VW | 1 | 2021-03-07 07:21:34 | 2021-03-09 04:36:34
21 | 2 | Ford | 0 | 2021-03-07 11:37:34 | 2021-03-10 04:36:34
prices
id | shopId | productId | price | dDateAdded
-----------------------------------------------------
224 | 1 | 18 | 2385 | 2021-03-09 12:39:57
225 | 2 | 19 | 1523 | 2021-03-09 13:14:44
226 | 1 | 20 | 5489 | 2021-03-09 17:32:18
227 | 1 | 18 | 2256 | 2021-03-10 18:22:13
228 | 2 | 19 | 1600 | 2021-03-10 21:33:21
229 | 1 | 20 | 5321 | 2021-03-10 14:15:56
230 | 1 | 18 | 2137 | 2021-03-11 05:55:25
231 | 2 | 19 | 1666 | 2021-03-11 17:31:49
232 | 1 | 20 | 5001 | 2021-03-11 20:18:01
This command return only 1 latest record from prices table for every product from products table for specific shopId
SELECT s.*, c.*, d.*
FROM shops AS s
LEFT JOIN products AS c ON c.shopId = s.id
LEFT JOIN (
SELECT productId, MAX(dDateAdded) MaxDate
FROM prices
GROUP BY productId
) MaxDates
ON MaxDates.productId = c.id
LEFT JOIN prices AS d ON d.productId = c.id AND d.shopId = s.id AND MaxDates.MaxDate = d.dDateAdded
WHERE s.id = ".$shopId."
For example if shopId=1 this command get only that records (I omitted here the data from the other tables that are retrieved):
230 | 1 | 18 | 2137 | 2021-03-11 05:55:25
232 | 1 | 20 | 5001 | 2021-03-11 20:18:01
But i want to get for example 2 latest records for every product where shopId=1, so the records which i want to get:
(shops)id | (shops)shopId | title | active | price | dDateAdded
1 | 2345 | Honda | 1 | 2256 | 2021-03-10 18:22:13
1 | 2345 | Honda | 1 | 2137 | 2021-03-10 14:15:56
1 | 2345 | VW | 1 | 5321 | 2021-03-11 05:55:25
1 | 2345 | VW | 1 | 5001 | 2021-03-11 20:18:01
To select N latest rows needs to allocate row number and to filter by N rows. However, the ROW_NUMBER function is not supported in MySQL 5.7.
So that you need to simulate the ROW_NUMBER function like the follwing:
You can get the desired result by adding subquery with row number to your query like the below:
DB Fiddle
SELECT
s.id,
s.shopId,
c.title,
c.active,
d.price,
d.dDateAdded
FROM shops AS s
LEFT JOIN products AS c ON c.shopId = s.id
LEFT JOIN prices AS d ON d.productId = c.id AND d.shopId = s.id
--
LEFT JOIN (
SELECT
p1.id,
COUNT(p2.dDateAdded) + 1 row_num
FROM prices p1 LEFT JOIN prices p2
ON p1.shopId = p2.shopId AND
p1.productId = p2.productId AND
p1.dDateAdded < p2.dDateAdded
GROUP BY p1.id, p1.shopId, p1.productId, p1.dDateAdded
) AS w
ON d.id=w.id
--
WHERE
s.id = 1 AND
w.row_num <= 2
DB Fiddle
SELECT
id,
shopId,
productId,
price,
dDateAdded
FROM (
SELECT p1.*,
(
SELECT COUNT(*)+1 FROM prices p2
WHERE
p1.shopId = p2.shopId AND
p1.productId = p2.productId AND
p1.dDateAdded < p2.dDateAdded
) row_num
FROM prices p1
) p
WHERE
shopId = 1 AND
row_num <= 2
ORDER BY id
DB Fiddle
SELECT p.* FROM prices p
INNER JOIN (
SELECT
p1.id,
COUNT(p2.dDateAdded) + 1 row_num
FROM prices p1 LEFT JOIN prices p2
ON p1.shopId = p2.shopId AND
p1.productId = p2.productId AND
p1.dDateAdded < p2.dDateAdded
GROUP BY
p1.id,
p1.shopId,
p1.productId,
p1.dDateAdded
) w
ON p.id=w.id
WHERE
p.shopId = 1 AND
w.row_num <= 2
ORDER BY p.id
Other way using a variable

Mysql select with multiple condition

I would need help creating a query
Table A
+------------+--------------------+-------+
| product_id | name | price |
+------------+--------------------+-------+
| 13 | Product 13 | 5 |
| 14 | Product 14 | 2 |
| 15 | Product 15 | 3 |
| 16 | Product 16 | 2 |
| 17 | Product 17 | 15 |
+------------+--------------------+-------+
Table B
+----+------------+-------------+
| id | product_id | taxonomy_id |
+----+------------+-------------+
| 10 | 13 | 5 |
| 11 | 13 | 2 |
| 12 | 14 | 3 |
| 13 | 15 | 2 |
| 14 | 16 | 15 |
| 14 | 16 | 5 |
| 14 | 16 | 19 |
| 14 | 16 | 21 |
| 14 | 16 | 18 |
+----+------------+-------------+
my attempt
SELECT *
FROM A
LEFT JOIN B ON B.product_id = A.product_id
WHERE IF(B.taxonomy_id IN ('5','15'),
IF(B.taxonomy_id IN ('2'), 1, 0), 0) = 1
GROUP BY A.product_id
I need it to give me back those results from table A for which it is true
B.taxonomy_id is "5" OR "15" and B.taxonomy_id is "2"
The result would be for this example -> product_id - 13
and I also need to get a number of results SELECT count(*) ... -> return is 1
Is it normal that your tables don't have an id column as a unique primary key ?
Anyway, here is what I came across, tell me if it works :
SELECT table_nameA.product_id
FROM table_nameA
LEFT JOIN table_nameB on table_nameA.product_id = table_nameB.product_id
WHERE taxonomy_id = 2 AND table_nameA.product_id IN
(SELECT table_nameA.product_id
FROM table_nameA
LEFT JOIN table_nameB on table_nameA.product_id = table_nameB.product_id
where taxonomy_id = 5 or taxonomy_id = 15
GROUP BY table_nameA.product_id, taxonomy_id)
Result is :
| product_id |
|------------|
| 13 |
About your count query, it is exactly the same.
SELECT count(table_nameA.product_id) as Quantity
FROM table_nameA
LEFT JOIN table_nameB on table_nameA.product_id = table_nameB.product_id
WHERE taxonomy_id = 2 AND table_nameA.product_id IN
(SELECT table_nameA.product_id
FROM table_nameA
LEFT JOIN table_nameB on table_nameA.product_id = table_nameB.product_id
where taxonomy_id = 5 or taxonomy_id = 15
GROUP BY table_nameA.product_id, taxonomy_id)
Result is :
| Quantity |
|----------|
| 1 |
Instead of doing filtering in the WHERE clause; you need to do this conditional filtering inside the HAVING clause. You can avoid LEFT JOIN, as the product should have taxonomies for them (2 AND (5 or 15)):
SELECT a.product_id
FROM tablea a
JOIN tableb b on b.product_id = a.product_id
GROUP BY a.product_id
HAVING SUM(b.taxonomy_id IN (5,15))
AND SUM(b.taxonomy_id = 2)
Result
| product_id |
| ---------- |
| 13 |
View on DB Fiddle
You can use exists:
select a.*
from a
where exists (select 1
from b
where b.product_id = a.product_id and
b.taxonomy_id in (5, 15)
) and
exists (select 1
from b
where b.product_id = a.product_id and
b.taxonomy_id in (2)
) ;
If you just wanted the product_ids, then I would recommend aggregation:
select b.product_id
from b
where b.taxonomy_id in (2, 5, 15)
group by b.product_id
having sum( b.taxonomy_id in (5, 15) ) > 0 and
sum( b.taxonomy_id in (2) ) > 0 ;
You can use either join with having clause or intersect function with 2 queries to get the output
13
in your senario.
Join with having clause:
select a.product_id from a inner join b on a.product_id = b.product_id group by a.product_id having (SUM (b.taxonomy_id IN (5,15)) and SUM (b.taxonomy_id in (2)));
Intersect with 2 queries:
select a.product_id from a where (a.product_id IN (select product_id from b where b.taxonomy_id = 2))
INTERSECT
select a.product_id from a where (a.product_id IN (select product_id from b where b.taxonomy_id in (5,15)));
For count use something like this which will return
1
as an output:
select COUNT(*) from (select a.product_id from a where (a.product_id IN (select product_id from b where b.taxonomy_id = 2))
INTERSECT
select a.product_id from a where (a.product_id IN (select product_id from b where b.taxonomy_id in (5,15)))) I;

Subquery mysql with where clause

Hello, Im stuck with mysql subquery, this is the table I have
table detail_order
==============================
id_detail | id_order | id_toko
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 1 | 4
table ket_detail
==================================
id_ket | id_detail | id_size | qty
1 | 1 | 7 | 3
2 | 1 | 9 | 1
3 | 1 | 5 | 2
4 | 2 | 7 | 8
table size
=================================
id_size | size | id_color | stock
7 | 40 | 6 | 30
9 | 42 | 6 | 20
5 | 39 | 5 | 30
table color
==========================
id_color | color
6 | green
5 | red
Im trying in subquery to show qty on table ket_detail with where clause, but when Im try it subquery return more than one row.
this is my query
SELECT dt.id_detail,
SUM(tk.qty) AS tot_order,
COUNT(dm.color) AS tot_color,
(SELECT ket.qty FROM ket_detail AS ket, t_size AS u
WHERE u.id_size=ket.id_size AND u.size = 40) AS size_40
FROM detail_order AS dt
LEFT JOIN ket_detail AS tk ON tk.id_detail=dt.id_detail
LEFT JOIN t_size AS u ON u.id_size = tk.id_size
LEFT JOIN t_color AS dm ON dm.id_color=u.id_color
WHERE dt.id_order = 1
GROUP BY dt.id_detail
but when I change size to 39 the data like this
id_detail | tot_order | tot_color | size_40
============================================
1 | 6 | 2 | 2
2 | 8 | 1 | 2
3 | NULL | 0 | 2
4 | NULL | 0 | 2
what do I want is the data like this
id_detail | tot_order | tot_color | size_40
============================================
1 | 6 | 2 | 3
2 | 8 | 1 | 8
3 | NULL | 0 | NULL
4 | NULL | 0 | NULL
You don't need a subquery to get the size = 39 or size = 40 data. You can use conditional aggregation instead:
SELECT dt.id_detail,
SUM(tk.qty) AS tot_order,
COUNT(dm.color) AS tot_color,
SUM(CASE
WHEN u.size = 39 THEN tk.qty
ELSE 0
END) AS size_39,
SUM(CASE
WHEN u.size = 40 THEN tk.qty
ELSE 0
END) AS size_40
FROM detail_order AS dt
LEFT JOIN ket_detail AS tk ON tk.id_detail=dt.id_detail
LEFT JOIN t_size AS u ON u.id_size = tk.id_size
LEFT JOIN t_color AS dm ON dm.id_color=u.id_color
WHERE dt.id_order = 1
GROUP BY dt.id_detail;
Demo here
The proper way to do it with a subquery is:
SELECT dt.id_detail,
SUM(tk.qty) AS tot_order,
COUNT(dm.color) AS tot_color,
(SELECT SUM(ket.qty)
FROM ket_detail AS ket
JOIN t_size AS u ON u.id_size=ket.id_size
WHERE ket.id_detail = dt.id_detail AND u.size = 40) AS size_40
FROM detail_order AS dt
LEFT JOIN ket_detail AS tk ON tk.id_detail=dt.id_detail
LEFT JOIN t_size AS u ON u.id_size = tk.id_size
LEFT JOIN t_color AS dm ON dm.id_color=u.id_color
WHERE dt.id_order = 1
GROUP BY dt.id_detail;
Demo here
If you need to select the total quantity for more than one sizes, then you have to repeat the subquery for each required size. Hence, I think, the first query provides a solution that is cleaner, easier to extend and more efficient.

Latest Group By MYSQL + link Table [duplicate]

This question already has answers here:
Retrieving the last record in each group - MySQL
(33 answers)
GROUP BY characteristic in mysql [closed]
(1 answer)
Closed 9 years ago.
I'm experiencing trouble with the a linking table and retrieving the lastUsed values.
Linking table:
link_devices_user
id | deviceId | shopId |
1 | 359 | 46 |
2 | 1339 | 46 |
3 | 1328 | 45 |
4 | 882 | 46 |
system_devices
id | carId | registerId | lastUsed |
359 | 350 | regi1 | 2014-01-03 09:00:00 |
1339 | 350 | regi2 | 2013-01-03 09:00:00 |
1328 | 160 | regi3 | 2012-01-03 09:00:00 |
882 | 150 | regi4 | 2014-01-03 08:59:00 |
Now I need to retrieve the latest unique carId from system_devices that is connected to shopId 46.
So in this case, the results should be.
882 | 150 | regi4 | 2014-01-03 08:59:00 |
359 | 350 | regi1 | 2014-01-03 09:00:00 |
I now have the following query. This gives me the unique carId but not the latest unique carId. What should i change?
SELECT system_devices.id,
carId,
FROM link_devices_user
INNER JOIN system_devices
ON link_devices_user.deviceId = system_devices.id
WHERE link_devices_user.shopid = '46'
GROUP BY system_devices.carId
ORDER BY system_devices.lastUsed DESC
Try this:
SELECT s.*
FROM system_devices s LEFT JOIN system_devices s1
ON (s.carId = s1.carId AND s.lastUsed < s1.lastUsed)
INNER JOIN link_devices_user ld ON s.id = ld.deviceId
WHERE (s1.id IS NULL) AND (ld.shopId = 46)
ORDER BY carId
http://sqlfiddle.com/#!2/158d9/4
You can check the SQL fiddle sample provided that gives the results required.
Try this:
SELECT A.id, A.carId, A.registerId, A.lastUsed
FROM (SELECT sd.id, sd.carId, sd.registerId, sd.lastUsed
FROM system_devices sd
INNER JOIN link_devices_user ld ON sd.id = ld.deviceId
WHERE ld.shopId = 46
ORDER BY sd.id, sd.carId DESC
) AS A
GROUP BY A.id
OR
SELECT sd.id, sd.carId, sd.registerId, sd.lastUsed
FROM system_devices sd
INNER JOIN link_devices_user ld ON sd.id = ld.deviceId
INNER JOIN (SELECT id, MAX(carId) carId FROM system_devices GROUP BY id) A ON A.id = sd.id AND A.carId = sd.carId
WHERE ld.shopId = 46
ORDER BY sd.id

Joining tables and making count operation - MySQL

I have those tables:
Members
---------------------------
MemberID | Name |.....
1
2
3
4
---------------------------
RentedMovies
---------------------------
MemberID | MovieID | DateOfLease | ReturnDate | .....
1 | 1 | 2012-12-20 | 2013-01-05
1 | 2 | 2012-12-15 | 2012-12-30
1 | 3 | 2012-12-16 | 2013-01-06
2 | 1 | 2012-12-17 | 2012-12-18
2 | 4 | 2012-12-18 | 2013-01-05
3 | 1 | 2012-12-19 | 2013-01-04
I need to get this:
--------------------------------------------------------
MemberID | NumberOfRentedMovies | ReturnData < curdate())
1 | 3 | 1
2 | 2 | 1
3 | 1 | 0
4 | 0 | 0
---------------------------------------------------------
And i used next code:
SELECT Members.MemberID,
COUNT(rented.MemberID) AS NumberOfRentedMovies,
COUNT(notTakenBackOnTime.idClana) AS NumberOfMoviesLate
FROM Members
left JOIN RentedMovies as rented ON rented.MemberID = Members.MemberID
left JOIN RentedMovies as notTakenBackOnTime ON notTakenBackOnTime.MemberID
= Members.MemberID AND notTakenBackOnTime.ReturnDate< CURDATE()
group by Members.MemberID
But it doesnt work corrextly!
And I also tried with this:
SELECT MemberID,my,my2
FROM Members as mem
JOIN (SELECT COUNT(* )AS my FROM RentedMovies) b
ON b.MemberID = mem.MemberID
JOIN (SELECT COUNT(* )AS my2 FROM RentedMovies WHERE ReturnDate< CURDATE()) c
ON c.MemberID = mem.MemberID
But i got some errors!
So the question is how to accomplish right solution?
You were close. Try this:
SELECT M.MemberID,
COUNT(RM.MemberID) NumberOfRentedMovies,
SUM(CASE WHEN RM.ReturnDate < CURDATE() THEN 1 ELSE 0 END) ReturnData
FROM Members M
LEFT JOIN RentedMovies RM
ON M.MemberID = RM.MemberID
GROUP BY M.MemberID
The desired result you showed can be accomplished by:
SELECT MemberID,
COALESCE(COUNT(MovieID), 0) AS NumberOfRentedMovies,
COALESCE(SUM(ReturnDate < CURDATE()), 0) AS NotYetReturned
FROM Members
LEFT JOIN RentedMovies USING (MemberID)
GROUP BY MemberID
See it in action: http://sqlfiddle.com/#!2/a192c/1