Using Where and Count on two tables - mysql

I have two tables
Foods
----------
ID Name
----------
1. Chips
2. Pizza
3. Fish
4. Pasta
People
-----------------
ID Name FoodID
-----------------
1. Robert 3
2. Norman 2
3. Leonard 4
4. Huey 3
What I'm supposed to do is retrieve any food that belongs to more than one person. Now I'm supposed to do this by means of COUNT and WHERE. Possibly might need to do an INNER JOIN.
It should be simple but I'm just not seeing it.

You want to join the tables on the common field. The WHERE is serving as an inner join. Then GROUP BY Foods.name aggregate rows by food type. Count is an aggregate operator that always works with the GROUP BY.
SELECT Foods.Name, Count(*)
FROM Foods, People
WHERE Foods.ID = People.Food
GROUP BY Foods.Name
HAVING COUNT(*)>1;
Omit the first count(*) if you just want the list of foods.

select f.name, p.name, count(f.id) as total from foods f, people p
where (f.id = p.FoodID)
group by f.name
having total > 1
order by f.name
http://sqlfiddle.com/#!9/b2a63/10

select * from food inner join people on people.id = food.id group by people.name

Related

SQL Select From Master - Detail Tables (Formatted Data)

I have two tables, named supplier and contacts.
The data in the contact table corresponds to a record on the supplier table.
Data of supplier
ID
Name
1
Hp
2
Huawei
Data for the contact
id
supplierId
Contact
1
1
John
2
1
Smith
3
1
Will
4
2
Doe
5
2
Wick
Now, I want to make a query that should return the following result
ID
Name
Contact
1
Hp
John, Smith, Will
2
Huawei
Doe, Wick
or should return the following result
ID
Name
Contact
Contact
Contact
1
Hp
John
Smith
Will
2
Huawei
Doe
Wick
You can use MySQL GROUP_CONCAT aggregation function to get your first output table. It's own ORDER BY clause will allow you to check the order of concatenation for the rows.
SELECT s.ID,
s.Name,
GROUP_CONCAT(c.Contact ORDER BY c.id)
FROM Supplier s
INNER JOIN Contact c
ON s.ID = c.supplierId
GROUP BY s.ID,
s.Name
You can use the window function ROW_NUMBER to assign a rank to each row inside the Contact table by partitioning on the supplier. Then split the contacts into three columns using an IF statement that will check for the three possible values of the ranking. The MAX aggregation function will allow you to remove the nulls.
SELECT s.ID,
s.Name,
MAX(IF(c.rn = 1, c.Contact, NULL)) AS Contact1,
MAX(IF(c.rn = 2, c.Contact, NULL)) AS Contact2,
MAX(IF(c.rn = 3, c.Contact, NULL)) AS Contact3
FROM Supplier s
INNER JOIN (SELECT *, ROW_NUMBER() OVER(PARTITION BY supplierId
ORDER BY id) AS rn
FROM Contact ) c
ON s.ID = c.supplierId
GROUP BY s.ID,
s.Name;
This second query may not work if you have more than three customers per supplier. In that case you either modify the query to contain the possible maximum amount of suppliers, or you use a prepared statement. If you really need such a solution, leave a comment below.
For a better understanding, you can play with these solutions here. The first solution will work on any MySQL version while the second one will work with MySQL 8.
Query to show the table like you want :
SELECT supplier.ID, supplier.Name, contact.Contact
FROM supplier
INNER JOIN contact
ON supplier.ID = contact.supplierId;

Find a record containing all or a part of a list of id of other table in a many-to-many relation on MySql/Jpa?

In my web application, I have 3 tables:
TAB A: Recipes (id, name)
TAB B: Recipes_Ingredients(id, fk_recipe,fk_ingredient, quantity) Bridge table
TAB C: Ingredients (id, name)
I need to find all the recipes(TAB A) that containing a provided list of ingredients (TAB C).
Es:
I provide a list of ingredients id like 111 (spaghetti), 222(pepper), 333(oil) and I need to find all the recipes that containing these ingredients. The query should return me all those recipes that contain at most these ingredients.
So if I run a search like this:
...
WHERE TAB_B.fk_ingredients IN (111,222,333) // IT DOESN'T WORKS AS I WISH
...
It must return a list of recipe that a list of recipes they contain MAX thath ingredients (111,222,333) and MINIMUM one of the ingredients I passed it.
Result Example:
id
name
list_fk_ingredients (es.)
1
Spaghetti with pepper
111,222
2
Spaghetti with oil
111,333
3
Pepper with nothing
222
4
Spaghetti with everything
111,222,333
I would also need a way to report the query back to JPA.
Thanks in advance!
Regards
Try this query:
SELECT ri.recipes_id
FROM recipes_ingredients ri
GROUP BY ri.recipes_id
HAVING COUNT(CASE WHEN ri.ingredients_id NOT IN (111,222,333) THEN 1 ELSE NULL END) =0;
First, you need a subquery where you join the tables then group them by Recipes
SELECT R.name, count(R.id) AS sum
FROM Recipes as R
join Recipes_Ingredients as RI on R.id=RI.fk_recipe
group by R.id
It will output you a list of all the recipes with a count of how many ingredients each have. I named the count of ingredients as sum in here.
You don't need to join the ingredients table.
Next, you just select the records which have 3 or less and 1 or more from this query using a WHERE statement.
SELECT R.name, sum
FROM (SELECT R.name, count(R.id) AS sum
FROM Recipes as R
join Recipes_Ingredients as RI on R.id=RI.fk_recipe
group by R.id) as T
WHERE sum <= 3
AND sum >=1

SQL - Counting how many associated records another table has

As I'm SQL beginner, I can't describe a problem in a simple way, so let me show you an example:
3 Tables:
PRODUCT
id
group_id
person_id
GROUP
id
name
PERSON
id
group_id
As you see, GROUP can have multiple PERSONs and PRODUCT can be connected with GROUP and PERSON.
From this point, I would like to count number of PERSONs having a PRODUCT within a GROUP
I don't really understand the background of IN or using another SELECT within FROM, so if that's the point, then I'm happy that I was one step before it lol.
SELECT
group.name as GROUP_name,
COUNT(DISTINCT person_id) AS PERSON_having_min_one_PRODUCT
FROM products
LEFT JOIN groups ON groups.id = products.group_id
LEFT JOIN persons ON persons.id = products.person_id;
With this data:
GROUP
ExampleGroupName1 has 3 PERSONs, but 2 of them has >0 PRODUCTS
ExampleGroupName2 has 3 PERSONs and all of them has >0 PRODUCTS
ExampleGroupName3 has 2 PERSONs, but none of them has the PRODUCT
ExampleGroupName4 has 2 PERSONs, but only 1 has >0 PRODUCT
I would like to have an output like this:
GROUP_name | PERSON_having_min_one_PRODUCT
ExampleGroupName1 | 2
ExampleGroupName2 | 3
ExampleGroupName4 | 1
I would like to count number of PERSONs having a PRODUCT within a GROUP
Note: I will assume the table product does not have the column group_id, since it is redundant and can lead to a lot of errors.
The following query will show you the result you want by joining the tables person and product:
select
count(distinct x.id)
from person x
join product p on p.person_id = x.id
where x.group_id = 123 -- choosing a specific group
and p.id = 456 -- choosing a specific product
This would rather be simple like below meaning all the groups with some group_id with count(persons) and those count who has some product via id used in having clause
Select group_id,
count( distinct id ) AS "PERSON_WITH_PRODUCT"
from
person group by group_id having id
in (Select id from product);

Need to find number of locations for each product purchased?

I have 2 tables (customer, transaction).
customer
id name location
1 samuel AZ
2 mithun CA
3 Robert NY
etc..
transaction
id customer_id product_id
1 1 12000
2 1 12222
3 3 15000
etc.
There are different products and different locations
By these columns I need to find number of locations one particular product was purchased?
I tried using joins.
My code was
select c.id, c.location, t.product_id
from customer c join transaction t
on (c.id = t.cid);
I was able to join two tables but I need count the number of transactions by tid.
Try grouping them - This provides the number of locations a particular product was purchased. This will includes duplicate entries for the locations but will answer your Number of transactions bit
select t.product_id, count(c.location)
from customer c join transaction t
on (c.id = t.cid)
group by 1;
To find "number of different locations per product id" simply use GROUP BY according to the product_id
select t.product_id, count(distinct c.location)
from transaction t
join customer c on (c.id = t.id)
group by product_id
use distinct in count to avoid counting the same location twice.

mysql left join duplicates

ive been searching for hours but cant find a solution. its a bit complicated so i'll break it down into a very simple example
i have two tables; people and cars
people:
name_id firstname
1 john
2 tony
3 peter
4 henry
cars:
name_id car_name
1 vw gulf
1 ferrari
2 mustang
4 toyota
as can be seen, they are linked by name_id, and john has 2 cars, tony has 1, peter has 0 and henry has 1.
i simply want to do a single mysql search for who has a (1 or more) car. so the anwser should be john, tony, henry.
the people table is the master table, and im using LEFT JOIN to add the cars. my problem arises from the duplicates. the fact that the table im joining has 2 entries for 1 id in the master.
im playing around with DISTINCT and GROUP BY but i cant seem to get it to work.
any help is much appreciated.
EDIT: adding the query:
$query = "
SELECT profiles.*, invoices.paid, COUNT(*) as num
FROM profiles
LEFT JOIN invoices ON (profiles.id=invoices.profileid)
WHERE (profiles.id LIKE '%$id%')
GROUP BY invoices.profileid
";
try this
select distinct p.name_id, firstname
from people p, cars c
where p.name_id = c.name_id
or use joins
select distinct p.name_id, firstname
from people p
inner join cars c
on p.name_id = c.name_id
If you only want to show people that have a car, then you should use a RIGHT JOIN. This will stop any results from the left table (people) to be returned if they didn't have a match in the cars table.
Group by the persons name to remove duplicates.
SELECT firstname
FROM people P
RIGHT JOIN cars C ON C.name_id = P.name_id
GROUP BY firstname
SELECT DISTINCT firstname
FROM people
JOIN cars ON cars.name_id = people.name_id;
If this doesn't work you might have to show us the full problem.
The way to propose it there's no need for a left join since you need at least a car per person. Left join is implicitely an OUTER join and is intended to return the results with 0 corresponding records in the joinned table.