Join table to get the latest rows from unique row - mysql

I have two table
The table structure goes something like this
Table A
╔══════╦════════╗
║ P_ID ║ P_NAME ║
╠══════╬════════╣
║ 1 ║ name1 ║
║ 2 ║ name2 ║
║ 3 ║ name3 ║
║ 4 ║ name5 ║
╚══════╩════════╝
Table B
╔═════╦════════╦════════╦═══════════╦═══════╗
║ ID ║ P_ID ║ C_ID ║ C_PRICE ║ TIME ║
╠═════╬════════╬════════╬═══════════╬═══════╣
║ 1 ║ 1 ║ 3 ║ 11 ║ 11111 ║
║ 2 ║ 2 ║ 4 ║ 22 ║ 22222 ║
║ 3 ║ 3 ║ 5 ║ 33 ║ 33333 ║
║ 4 ║ 3 ║ 6 ║ 44 ║ 44444 ║
║ 5 ║ 3 ║ 6 ║ 55 ║ 55555 ║
║ 6 ║ 4 ║ 7 ║ 66 ║ 66666 ║
╚═════╩════════╩════════╩═══════════╩═══════╝
The requirement is
1. Join two table
2. Group By C_ID
3. The latest rows in Group By
I tried to modify the answer By Bill Karwin from How do I join the most recent row in one table to another table?
SELECT e.*, s1.*
FROM table_a e
INNER JOIN
table_b s1
ON (e.p_id = s1.p_id)
LEFT OUTER JOIN table_b s2
ON (e.p_id = s2.p_id AND s1.id < s2.id)
WHERE s2.p_id IS NULL;
but I could not achieve what I want. From his answer I will get
╔═════╦════════╦════════╦═══════════╦═══════╦═════════╗
║ ID ║ P_ID ║ C_ID ║ C_PRICE ║ TIME ║ P_NAME ║
╠═════╬════════╬════════╬═══════════╬═══════╬═════════╣
║ 1 ║ 1 ║ 3 ║ 11 ║ 11111 ║ name1 ║
║ 2 ║ 2 ║ 4 ║ 22 ║ 22222 ║ name2 ║
║ 5 ║ 3 ║ 6 ║ 55 ║ 55555 ║ name3 ║
║ 6 ║ 4 ║ 7 ║ 66 ║ 66666 ║ name5 ║
╚═════╩════════╩════════╩═══════════╩═══════╩═════════╝
But the output what I want is as below ( dublicate P_ID is ok but for each dublicate P_ID should not have dublicate C_ID )
╔═════╦════════╦════════╦═══════════╦═══════╦═════════╗
║ ID ║ P_ID ║ C_ID ║ C_PRICE ║ TIME ║ P_NAME ║
╠═════╬════════╬════════╬═══════════╬═══════╬═════════╣
║ 1 ║ 1 ║ 3 ║ 11 ║ 11111 ║ name1 ║
║ 2 ║ 2 ║ 4 ║ 22 ║ 22222 ║ name2 ║
║ 3 ║ 3 ║ 5 ║ 33 ║ 33333 ║ name3 ║
║ 5 ║ 3 ║ 6 ║ 55 ║ 55555 ║ name3 ║
║ 6 ║ 4 ║ 7 ║ 66 ║ 66666 ║ name5 ║
╚═════╩════════╩════════╩═══════════╩═══════╩═════════╝

SELECT e.*, s1.*
FROM table_a e INNER JOIN
(SELECT * FROM (SELECT * FROM table_b ORDER BY time DESC) temp GROUP BY c_id) s1;
The innermost ORDER BY ensures the for the same c_id the desired row always comes first, the outter GROUP BY will group on c_id, and having not specified otherwise will return the first row found for each group.

You must
Join two table
Group By C_ID
Number row for each group desc ordered by chosen field (last imply order!)
Filter by row number = 1.
This can help you for numbering rows.

Related

How to get corresponding id with minimum value of a row in MySQL?

I have two tables named deals and mp_details. Columns deal_id and mp_details_id are the two primary keys. There is a relation between the two tables using the deal_mp_id column where it works as a foreign key. I want to fetch all the minimum records of column name deal_selling_price with group by mp_details_id. Here are the tables:
deals
╔═════════╦════════════╦════════════════════╗
║ deal_id ║ deal_mp_id ║ deal_selling_price ║
╠═════════╬════════════╬════════════════════╣
║ 3 ║ 1 ║ 425 ║
║ 4 ║ 1 ║ 540 ║
║ 5 ║ 2 ║ 340 ║
║ 6 ║ 2 ║ 315 ║
║ 7 ║ 3 ║ 425 ║
║ 8 ║ 3 ║ 720 ║
║ 9 ║ 4 ║ 382.5 ║
║ 10 ║ 4 ║ 495 ║
║ 11 ║ 5 ║ 595 ║
║ 12 ║ 5 ║ 720 ║
╚═════════╩════════════╩════════════════════╝
mp_details
╔═══════════════╦═════════════════════╗
║ mp_details_id ║ mp_details_name ║
╠═══════════════╬═════════════════════╣
║ 1 ║ Olive Bar & Kitchen ║
║ 2 ║ Thai High ║
║ 3 ║ Tonino ║
║ 4 ║ Impromptu ║
║ 5 ║ Zerruco ║
╚═══════════════╩═════════════════════╝
And I want this kind of result:
╔═════════╦════════════╦════════════════════╗
║ deal_id ║ deal_mp_id ║ deal_selling_price ║
╠═════════╬════════════╬════════════════════╣
║ 3 ║ 1 ║ 425 ║
║ 6 ║ 2 ║ 315 ║
║ 7 ║ 3 ║ 425 ║
║ 9 ║ 4 ║ 382.5 ║
║ 11 ║ 5 ║ 595 ║
╚═════════╩════════════╩════════════════════╝
The following query will give you the result set from your screen capture above:
SELECT d1.deal_id, d1.deal_mp_id, d2.minPrice
FROM deals d1
INNER JOIN
(
SELECT deal_mp_id, MIN(deal_selling_price) AS minPrice
FROM deals
GROUP BY deal_mp_id
) d2
ON d1.deal_mp_id = d2.deal_mp_id AND d1.deal_selling_price = d2.minPrice
If you also want to include information from the mp_details table, you can do an additional join like this:
SELECT d1.deal_id, d1.deal_mp_id, d2.minPrice, mp.mp_details_name
FROM deals d1
INNER JOIN
(
SELECT deal_mp_id, MIN(deal_selling_price) AS minPrice
FROM deals
GROUP BY deal_mp_id
) d2
ON d1.deal_mp_id = d2.deal_mp_id AND d1.deal_selling_price = d2.minPrice
INNER JOIN mp_details mp
ON d1.deal_mp_id = mp.mp_details_id
Follow the link below for a running demo:
SQLFiddle
Try below query
select
D.Deal_id, MD.mp_details_id, MIN(D.deal_selling_price)
FROM
deals D inner join mp_details MD
ON
D.Deal_id = MD.mp_details_id
GROUP BY
D.Deal_id, MD.mp_details_id
Use this query:
SELECT d.deal_id, d.deal_mp_id, d.deal_selling_price
FROM deals d
JOIN
(
SELECT deal_mp_id, MIN(deal_selling_price) AS min_selling_price
FROM deals
GROUP BY deal_mp_id
) m
ON d.deal_mp_id = m.deal_mp_id AND d.deal_selling_price = m.min_selling_price

Unable to figure this join giving wrong results

I have two tables I want to join but I am unable to get the desired answer.
I am trying to joing two table on the base of two primary key and grouping thrid column and want to get count of third column.
Table 1:
╔══════╦══════╗
║ D_ID ║ E_ID ║
╠══════╬══════╣
║ 5 ║ 25 ║
║ 5 ║ 26 ║
║ 5 ║ 27 ║
║ 10 ║ 30 ║
║ 10 ║ 31 ║
║ 10 ║ 32 ║
╚══════╩══════╝
Table 2:
╔══════╦══════╦══════╗
║ D_ID ║ E_ID ║ L_ID ║
╠══════╬══════╬══════╣
║ 5 ║ 25 ║ 1 ║
║ 5 ║ 25 ║ 2 ║
║ 5 ║ 25 ║ 3 ║
║ 5 ║ 25 ║ 4 ║
║ 5 ║ 26 ║ 5 ║
║ 5 ║ 26 ║ 6 ║
║ 5 ║ 26 ║ 7 ║
║ 5 ║ 26 ║ 8 ║
║ 5 ║ 27 ║ 9 ║
║ 10 ║ 30 ║ 10 ║
║ 10 ║ 30 ║ 11 ║
║ 10 ║ 31 ║ 12 ║
║ 10 ║ 31 ║ 13 ║
║ 10 ║ 32 ║ 14 ║
╚══════╩══════╩══════╝
Desired Output:
╔══════╦══════╦═════════════╗
║ D_ID ║ E_ID ║ Count(L_ID) ║
╠══════╬══════╬═════════════╣
║ 5 ║ 25 ║ 4 ║
║ 5 ║ 26 ║ 4 ║
║ 5 ║ 27 ║ 1 ║
║ 10 ║ 30 ║ 2 ║
║ 10 ║ 31 ║ 2 ║
║ 10 ║ 32 ║ 1 ║
╚══════╩══════╩═════════════╝
Using this Query:
select a.D_ID, a.E_ID, count(b.L_ID)
from table1 a, table2 b
where a.D_ID = b.D_ID and
a.E_ID = b.E_ID
group by a.D_ID, a.E_ID
Join is important because table 2 is huge table with millions of records and table 1 has only few thousand records that what I need. I dont need all D_ID and E_ID's. I only need those D_ID and E_ID which are in Table1.
just add a DISTINCT clause to the count like so
SELECT
a.D_ID, a.E_ID, COUNT(DISTINCT b.L_ID)
FROM table1 a, table2 b
WHERE a.D_ID = b.D_ID
AND a.E_ID = b.E_ID
GROUP BY a.D_ID, a.E_ID
my personal preference for joining tables is like so
SELECT a.d_id, a.e_id, COUNT(DISTINCT b.l_id)
FROM table1 a
JOIN table2 b ON a.D_ID = b.D_ID
AND a.E_ID = b.E_ID
GROUP BY a.D_ID, a.E_ID
see this DEMO executing all two queries with the correct result set

Need help to retrieve data from three MySQL tables

I have three tables named "users","user_hobbies" and "hobbies". Below is the sample tables with values;Below is the users table with fields id, name and age
╔════╦══════╦═════╗
║ ID ║ NAME ║ AGE ║
╠════╬══════╬═════╣
║ 1 ║ abc ║ 23 ║
║ 2 ║ xyz ║ 24 ║
║ 3 ║ pqr ║ 21 ║
╚════╩══════╩═════╝
and below is user_hobbies table with fields id, user_id and hobby_id
╔════╦═════════╦══════════╗
║ ID ║ USER_ID ║ HOBBY_ID ║
╠════╬═════════╬══════════╣
║ 1 ║ 1 ║ 1 ║
║ 2 ║ 1 ║ 2 ║
║ 3 ║ 1 ║ 3 ║
║ 4 ║ 2 ║ 4 ║
║ 5 ║ 2 ║ 3 ║
║ 6 ║ 2 ║ 5 ║
║ 7 ║ 3 ║ 2 ║
║ 8 ║ 4 ║ 6 ║
╚════╩═════════╩══════════╝
. Below is the hobbies table with fields id and desc
╔════╦═══════════╗
║ ID ║ DESC ║
╠════╬═══════════╣
║ 1 ║ music ║
║ 2 ║ chatting ║
║ 3 ║ cricket ║
║ 4 ║ badminton ║
║ 5 ║ chess ║
║ 6 ║ cooking ║
╚════╩═══════════╝
. The actual requirement is that i need a query to retrieve name, age, hobby_id and desc (see an example below)
╔══════╦═════╦══════════╦═════════════════════════╗
║ NAME ║ AGE ║ HOBBYID ║ DESC ║
╠══════╬═════╬══════════╬═════════════════════════╣
║ abc ║ 23 ║ 1,2,3 ║ music,chatting,cricket ║
║ pqr ║ 21 ║ 2 ║ chatting ║
║ xyz ║ 24 ║ 4,3,5 ║ badminton,cricket,chess ║
╚══════╩═════╩══════════╩═════════════════════════╝
You need to join the tables first and use an aggregate function called GROUP_CONCAT().
SELECT a.Name,
a.Age,
GROUP_CONCAT(c.ID) hobbyIDs,
GROUP_CONCAT(c.desc) descList
FROM users a
INNER JOIN user_hobbies b
ON a.ID = b.user_ID
INNER JOIN hobbies c
ON b.hobby_ID = c.ID
GROUP BY a.Name, a.Age
SQLFiddle Demo
MySQL GROUP_CONCAT()
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
OUTPUT
╔══════╦═════╦══════════╦═════════════════════════╗
║ NAME ║ AGE ║ HOBBYIDS ║ DESCLIST ║
╠══════╬═════╬══════════╬═════════════════════════╣
║ abc ║ 23 ║ 1,2,3 ║ music,chatting,cricket ║
║ pqr ║ 21 ║ 2 ║ chatting ║
║ xyz ║ 24 ║ 4,3,5 ║ badminton,cricket,chess ║
╚══════╩═════╩══════════╩═════════════════════════╝

Multiple column in order by clause - mysql

I have two columns in a table say, LIKE and FAVORITES (int value)
See the chart:
╔════╦══════╦══════════╗
║ ID ║ LIKE ║ FAVORITE ║
╠════╬══════╬══════════╣
║ 1 ║ 25 ║ 9 ║
║ 2 ║ 5 ║ 17 ║
║ 3 ║ 6 ║ 1 ║
║ 4 ║ 45 ║ 0 ║
║ 5 ║ 3 ║ 44 ║
╚════╩══════╩══════════╝
Now, I want to select the Maximum Like and Favorites IDs from the SELECT clause.
I have tried
SELECT ID from TABLE WHERE CONDITION ORDER BY LIKE,FAVORITES DESC
But the result shows the rows based on LIKE DESC order.
The result should be
╔════╗
║ ID ║
╠════╣
║ 5 ║
║ 4 ║
║ 1 ║
║ 2 ║
║ 3 ║
╚════╝
I think you need to add those two columns. eg,
SELECT ID
FROM tableName
ORDER BY `LIKE` + FAVORITE DESC
SQLFiddle Demo
Result:
╔════╗
║ ID ║
╠════╣
║ 5 ║
║ 4 ║
║ 1 ║
║ 2 ║
║ 3 ║
╚════╝

Substraction from two different tables in SQL

Since my problem is somewhat particular, I haven't yet found and answer, after very long searches, so here it goes: I have two tables: In_Stock and Out_Stock. I use the following selects:
IN_Stock:
select
INs.CatID as CategoryID,
INs.SubCatID as SubcategoryID, Sum(INs.Quantity) as QuantityIN
from IN_Stock INs
group by INs.CatID, INs.SubCatID
╔════════════╦═══════════════╦════════════╗
║ CategoryID ║ SubcategoryID ║ QuantityIN ║
╠════════════╬═══════════════╬════════════╣
║ 2 ║ 9 ║ 0 ║
║ 1 ║ 16 ║ 8 ║
║ 1 ║ 27 ║ 5 ║
║ 1 ║ 30 ║ 160 ║
║ 1 ║ 31 ║ 6 ║
║ 1 ║ 39 ║ 35 ║
║ 1 ║ 40 ║ 7 ║
║ 2 ║ 44 ║ 13 ║
║ 2 ║ 54 ║ 6 ║
║ 2 ║ 70 ║ 5 ║
║ 3 ║ 87 ║ 3,5 ║
╚════════════╩═══════════════╩════════════╝
OUT_Stock:
select
OUTs.CatID as CategoryID,
OUTs.SubCatID as SubcategoryID,
Sum(OUTs.Quantity) as QuantityOUT
from OUT_Stock OUTs
group by OUTs.CatID, OUTs.SubCatID
╔════════════╦═══════════════╦═════════════╗
║ CategoryID ║ SubcategoryID ║ QuantityOUT ║
╠════════════╬═══════════════╬═════════════╣
║ 1 ║ 30 ║ 30 ║
║ 1 ║ 39 ║ 15 ║
╚════════════╩═══════════════╩═════════════╝
What I get is this table bellow (and it's obviously not right).
select
INs.CatID as CategoryID,
INs.SubCatID as SubcategoryID,
Sum(INs.Quantity) as QuantityIN,
SUM(OUTs.Quantity) as QuantityOUT,
SUM(INs.Quantity)- SUM(OUTs.Quantity) as RemainingQuantity
from IN_Stock INs
left join OUT_Stock OUTs on INs.CatID=OUTs.CatID and INs.SubCatid=OUTs.SubCatid
group by INs.catid, INs.subcatid
╔════════════╦═══════════════╦═════════════╦════════════╦═══════════════════╗
║ CategoryID ║ SubcategoryID ║ QuantityIN ║ QuantityOUT║ RemainingQuantity ║
╠════════════╬═══════════════╬═════════════╬════════════╬═══════════════════╣
║ 2 ║ 9 ║ 0 ║ ║ ║
║ 1 ║ 16 ║ 8 ║ ║ ║
║ 1 ║ 27 ║ 5 ║ ║ ║
║ 1 ║ 30 ║ 320 ║ 150 ║ 170 ║
║ 1 ║ 31 ║ 6 ║ ║ ║
║ 1 ║ 39 ║ 35 ║ 30 ║ 5 ║
║ 1 ║ 40 ║ 7 ║ ║ ║
║ 2 ║ 44 ║ 13 ║ ║ ║
║ 2 ║ 54 ║ 6 ║ ║ ║
║ 2 ║ 70 ║ 5 ║ ║ ║
║ 3 ║ 87 ║ 3,5 ║ ║ ║
╚════════════╩═══════════════╩═════════════╩════════════╩═══════════════════╝
What i want is to make a select in SQL that returns something like the table bellow... and I would like to know if and how can I see in RemaningStock collumn: 130 where SubcategoryID=30 and 20 where SubCategoryID=39.
╔════════════╦═══════════════╦════════════╦════════════╦═══════════════════╗
║ CategoryID ║ SubcategoryID ║ QuantityIN ║ QuantityIN ║ RemainingQuantity ║
╠════════════╬═══════════════╬════════════╬════════════╬═══════════════════╣
║ 2 ║ 9 ║ 0 ║ ║ ║
║ 1 ║ 16 ║ 8 ║ ║ ║
║ 1 ║ 27 ║ 5 ║ ║ ║
║ 1 ║ 30 ║ 160 ║ 30 ║ 130 ║
║ 1 ║ 31 ║ 6 ║ ║ ║
║ 1 ║ 39 ║ 35 ║ 15 ║ 20 ║
║ 1 ║ 40 ║ 7 ║ ║ ║
║ 2 ║ 44 ║ 13 ║ ║ ║
║ 2 ║ 54 ║ 6 ║ ║ ║
║ 2 ║ 70 ║ 5 ║ ║ ║
║ 3 ║ 87 ║ 3,5 ║ ║ ║
╚════════════╩═══════════════╩════════════╩════════════╩═══════════════════╝
Both tables have one or multiple records for a certain category or subcategory
Any help is much appreciated. Many thanks!
Either SQL or Access VBA code is good for me.
PS: As this is my first post please be "gentle".
The main problem is that your final query makes the joins on individual rows in the initial dataset and only then performs the aggregation, whereas you would want to perform the joins on the intermediate sums.
Assuming this test data, for example:
CREATE TABLE table_in (
id INTEGER,
value INTEGER
);
CREATE TABLE table_out (
id INTEGER,
value INTEGER
);
INSERT INTO table_in(id, value) VALUES
(1, 120),
(1, 10);
INSERT INTO table_out(id, value) VALUES
(1, 30);
The way you're writing the LEFT JOIN in your last query:
SELECT t1.value AS val1, t2.value AS val2
FROM table_in t1 LEFT JOIN table_out t2 ON t1.id=t2.id;
would produce these rows, before aggregation:
ID VAL1 VAL2
1 120 30
1 10 30
Here, the sum would then give this:
ID SUM(VAL1) SUM(VAL2)
1 130 60
This will happen any time there's more than one row for the conditions used for the join.
You need to perform the join after the aggregate operations, since you want to compare the sum of all inputs, to the sum of all outputs.
This can be done using subselect statements, or CTEs.
For example:
WITH sum_in AS (
SELECT id, SUM(value) AS all_in
FROM table_in
GROUP BY id
), sum_out AS (
SELECT id, SUM(value) AS all_out
FROM table_out
GROUP BY id
)
SELECT t1.id, all_in, all_out, all_in - all_out
FROM sum_in t1 LEFT JOIN sum_out t2 ON t1.id=t2.id
You can use subqueries to get what you want, for example:
SELECT *
FROM (SELECT INs.catid AS CategoryID,
INs.subcatid AS SubcategoryID,
SUM(INs.quantity) AS QuantityIN
FROM in_stock INs
GROUP BY INs.catid,
INs.subcatid) AS a
LEFT JOIN (SELECT OUTs.catid AS CategoryID,
OUTs.subcatid AS SubcategoryID,
SUM(OUTs.quantity) AS QuantityOUT
FROM out_stock OUTs
GROUP BY OUTs.catid,
OUTs.subcatid) AS b
ON ( a.subcategoryid = b.subcategoryid )
AND ( a.categoryid = b.categoryid );
From this, it is very easy indeed to edit and modify the query using the Query Design Window in MS Access
SELECT a.categoryid,
a.subcategoryid,
a.quantityin,
b.quantityout,
[quantityin] - [quantityout] AS RemainingQuantity
FROM (SELECT INs.catid AS CategoryID,
INs.subcatid AS SubcategoryID,
SUM(INs.quantity) AS QuantityIN
FROM in_stock INs
GROUP BY INs.catid,
INs.subcatid) AS a
LEFT JOIN (SELECT OUTs.catid AS CategoryID,
OUTs.subcatid AS SubcategoryID,
SUM(OUTs.quantity) AS QuantityOUT
FROM out_stock OUTs
GROUP BY OUTs.catid,
OUTs.subcatid) AS b
ON ( a.subcategoryid = b.subcategoryid )
AND ( a.categoryid = b.categoryid );