Get Records Not Present in Other Table - mysql

I have two tables:
all_countries
╔════╦═════════════╗
║ ID ║ COUNTRY ║
╠════╬═════════════╣
║ 1 ║ USA ║
║ 2 ║ China ║
║ 3 ║ India ║
║ 4 ║ France ║
║ 5 ║ UK ║
║ 6 ║ Australia ║
║ 7 ║ Philippines ║
╚════╩═════════════╝
supported_countries
╔════════════╦═══════════╦═══════════╗
║ COUNTRY_ID ║ COUNTRY ║ FILTER_ID ║
╠════════════╬═══════════╬═══════════╣
║ 1 ║ USA ║ 1 ║
║ 2 ║ China ║ 1 ║
║ 3 ║ India ║ 1 ║
║ 4 ║ France ║ 2 ║
║ 1 ║ USA ║ 2 ║
║ 6 ║ Australia ║ 2 ║
╚════════════╩═══════════╩═══════════╝
Query:
SELECT a.*
FROM all_countries a
LEFT JOIN supported_countries s
ON a.id = s.country_id
WHERE s.country_id IS NULL;
So as per above example I should get.
UK
Philippines
It works fine, but what if, if I filter the country example I choose to filter = 2.
i get zero result.
SELECT a.*
FROM all_countries a
LEFT JOIN supported_countries s
ON a.id = s.country_id
WHERE s.filter = 2 AND s.country_id IS NULL;
supposed to be i want to get this result, if filter = 2.
╔════╦═════════════╗
║ ID ║ COUNTRY ║
╠════╬═════════════╣
║ 2 ║ China ║
║ 3 ║ India ║
║ 5 ║ UK ║
║ 7 ║ Philippines ║
╚════╩═════════════╝
Am I doing the correct query?

add the condition on the ON clause,
SELECT a.*
FROM all_countries a
LEFT JOIN supported_countries s
ON a.id = s.country_id AND
s.filter_ID = 2 -- <<=== HERE
WHERE s.country_id IS NULL;
SQLFiddle Demo
Result:
╔════╦═════════════╗
║ ID ║ COUNTRY ║
╠════╬═════════════╣
║ 2 ║ China ║
║ 3 ║ India ║
║ 5 ║ UK ║
║ 7 ║ Philippines ║
╚════╩═════════════╝

Related

How to select Group By groups which contain a specific value?

I have a table of orders which follows the below format:
╔══════════╦══════════╦══════════╦═══════╦══════════════╦═══════════════╗
║ Order ID ║ Subtotal ║ Shipping ║ Total ║ Product Name ║ Product Price ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 1 ║ 30 ║ 5 ║ 35 ║ Apple ║ 10 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 1 ║ ║ ║ ║ Banana ║ 10 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 1 ║ ║ ║ ║ Coffee ║ 10 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 2 ║ 30 ║ 5 ║ 35 ║ Peach ║ 20 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 2 ║ ║ ║ ║ Banana ║ 10 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 3 ║ 20 ║ 3 ║ 23 ║ Peach ║ 20 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 4 ║ 40 ║ 10 ║ 50 ║ Apple ║ 10 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 4 ║ ║ ║ ║ Coffee ║ 10 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 4 ║ ║ ║ ║ Peach ║ 20 ║
╚══════════╩══════════╩══════════╩═══════╩══════════════╩═══════════════╝
All order numbers come as totals - subtotal and shipping with the lines below blank.
I am trying to look into the sales of a specific product.
For example I'd like to have a query which selects all orders which contain "Banana" and also returns the subtotal, shipping and total for the order as well as the product price (which are sometimes not on the same line):
I.e. it'd return this:
╔══════════╦══════════╦══════════╦═══════╦══════════════╦═══════════════╗
║ Order ID ║ Subtotal ║ Shipping ║ Total ║ Product Name ║ Product Price ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 1 ║ 30 ║ 5 ║ 35 ║ Banana ║ 10 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 2 ║ 30 ║ 5 ║ 35 ║ Banana ║ 10 ║
╚══════════╩══════════╩══════════╩═══════╩══════════════╩═══════════════╝
You can join the table to itself:
select
b.`Order ID`,
max(s.Subtotal) as 'Subtotal',
max(s.Shipping) as 'Shipping',
max(s.Total) as 'Total',
b.`Product Name`,
b.`Product Price`
from orders b
join orders s on s.`Order ID`=b.`Order ID`
where b.`Product Name`='Banana'
group by
b.`Order ID`,
b.`Product Name`,
b.`Product Price`
See a dbfiddle.

sql 2008 remove duplicates from inner join

Using SQL 2008 R2. I am trying to find Employees that are Active, but were previously employees in one of our other companies. The following code works; however, I noticed that if the Employee has worked for more than two companies, I get duplicates. Is there another way that I need to write this so that I do not get duplicates? I have tried using the Group By and case with when exist and nothing seems to work.
SAMPLE DATA
╔═════════════╦══════╦══════════╦══════════╦══════════╦══════════╗
║ SSN ║ PRCo ║ Employee ║ FullName ║ HireDate ║ ActiveYN ║
╠═════════════╬══════╬══════════╬══════════╬══════════╬══════════╣
║ 123-45-6789 ║ 17 ║ 456789 ║ John Doe ║ 05/27/13 ║ Y ║
╠═════════════╬══════╬══════════╬══════════╬══════════╬══════════╣
║ 123-45-6789 ║ 23 ║ 456789 ║ John Doe ║ 08/22/11 ║ N ║
╠═════════════╬══════╬══════════╬══════════╬══════════╬══════════╣
║ 123-45-6789 ║ 1 ║ 456789 ║ John Doe ║ 12/03/07 ║ N ║
╠═════════════╬══════╬══════════╬══════════╬══════════╬══════════╣
║ 999-99-9999 ║ 17 ║ 999999 ║ Jane Doe ║ 05/27/13 ║ Y ║
╠═════════════╬══════╬══════════╬══════════╬══════════╬══════════╣
║ 999-99-9999 ║ 23 ║ 999999 ║ Jane Doe ║ 01/26/09 ║ N ║
╚═════════════╩══════╩══════════╩══════════╩══════════╩══════════╝
Using the following code
select distinct p1.SSN, p1.PRCo, p1.Employee, n.FullName, p1.HireDate, p1.ActiveYN,
case when p1.ActiveYN = 'Y' then 'Y'
when p2.ActiveYN = 'Y' then 'Y'
else 'N' end as AnyActiveCo
from PREH as p1
inner join PREH as p2 on p1.SSN=p2.SSN
left outer join PREHFullName as n on p1.PRCo=n.PRCo and p1.Employee=n.Employee
where p1.PRCo<>p2.PRCo
RESULTS; Row 3 & 5 are duplicates and do not have the desired AnyActiveCo result for an employee that was in 3 different companies; however employees with just 2 companies show fine.
╔═════╦═════════════╦══════╦══════════╦══════════╦══════════╦══════════╦═════════════╗
║ Row ║ SSN ║ PRCo ║ Employee ║ FullName ║ HireDate ║ ActiveYN ║ AnyActiveCo ║
╠═════╬═════════════╬══════╬══════════╬══════════╬══════════╬══════════╬═════════════╣
║ 1 ║ 123-45-6789 ║ 17 ║ 456789 ║ John Doe ║ 05/27/13 ║ Y ║ Y ║
╠═════╬═════════════╬══════╬══════════╬══════════╬══════════╬══════════╬═════════════╣
║ 2 ║ 123-45-6789 ║ 23 ║ 456789 ║ John Doe ║ 08/22/11 ║ N ║ Y ║
╠═════╬═════════════╬══════╬══════════╬══════════╬══════════╬══════════╬═════════════╣
║ 3 ║ 123-45-6789 ║ 23 ║ 456789 ║ John Doe ║ 08/22/11 ║ N ║ N ║
╠═════╬═════════════╬══════╬══════════╬══════════╬══════════╬══════════╬═════════════╣
║ 4 ║ 123-45-6789 ║ 1 ║ 456789 ║ John Doe ║ 12/03/07 ║ N ║ Y ║
╠═════╬═════════════╬══════╬══════════╬══════════╬══════════╬══════════╬═════════════╣
║ 5 ║ 123-45-6789 ║ 1 ║ 456789 ║ John Doe ║ 12/03/07 ║ N ║ N ║
╠═════╬═════════════╬══════╬══════════╬══════════╬══════════╬══════════╬═════════════╣
║ 6 ║ 999-99-9999 ║ 17 ║ 999999 ║ Jane Doe ║ 05/27/13 ║ Y ║ Y ║
╠═════╬═════════════╬══════╬══════════╬══════════╬══════════╬══════════╬═════════════╣
║ 7 ║ 999-99-9999 ║ 23 ║ 999999 ║ Jane Doe ║ 01/26/09 ║ N ║ Y ║
╚═════╩═════════════╩══════╩══════════╩══════════╩══════════╩══════════╩═════════════╝

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

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 ║
╚══════╩═════╩══════════╩═════════════════════════╝

Join table to get the latest rows from unique row

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.