Selecting rows except some others - mysql

ID | fruit | who | days_ago |
----------------------------------
1 | orange | Adam | 2 |
2 | banana | Adam | 3 |
3 | apple | Adam | 4 |
4 | kiwi | Adam | 2 |
6 | banana | Jimmy | 3 |
7 | apple | Jimmy | 5 |
8 | grapes | Jimmy | 1 |
9 | orange | Carol | 2 |
10 | grapes | Carol | 6 |
11 | lemon | Carol | 3 |
And my problem is:
The table contained information about who bought what fruit and when (when is an extra information I just need to keep).
I need to select all the fruits that Adam didn't buy.
ID | fruit | who | days_ago |
----------------------------------
8 | grapes | Jimmy | 1 |
10 | grapes | Carol | 6 |
11 | lemon | Carol | 3 |
And if Jimmy bought them, I don't want to know if Carol bought them too.
And my result should be this:
ID | fruit | who | days_ago |
----------------------------------
8 | grapes | Jimmy | 1 |
11 | lemon | Carol | 3 |
When I GROUP BY fruit, I lose information about who and days_ago (I don't understand how they're chosen).
And when I select unique fruits and drop all that Adam bought, I lose grapes which both Jimmy and Carol bought.
This isn't the actual table I'm working on. Just a simplification of what I'm struggling with.
Any ideas?

If you want the fruits that Adam didn't buy, you can use a subquery for this. Have the subquery select the fruits he did buy, and then have the main query say "not those".
SELECT *
FROM fruits
WHERE fruit NOT IN(
SELECT fruit
FROM fruits
WHERE who = "Adam"
)
DEMO: http://sqlfiddle.com/#!9/3974d/1
When you use GROUP BY, you are combining multiple rows into one. The other rows' data isn't gone, just hidden. Try using GROUP_CONCAT to see the list of who fields.
SELECT ID, fruit,
GROUP_CONCAT(who) as who,
GROUP_CONCAT(days_ago) AS days_ago
FROM fruits
WHERE fruit NOT IN(
SELECT fruit
FROM fruits
WHERE who = "Adam"
)
GROUP BY fruit
DEMO: http://sqlfiddle.com/#!9/3974d/3

Related

MYSQL stock gap prediction

I've been scratching my head on a way to get this working for quite some time now, and as it's so specific I can't seem to find the answer elsewhere on StackOverflow. Any answers or suggestions would be appreciated.
I'm working to produce a report on that will inform a user of stock management and consumption. Calculating this with the values of current_stock and daily_stock_consumption is easy... But when we add shipments incoming into the process things become very complicated. Getting MYSQL to return the first day that each stock reaches 0 is leaving me blank.
For instance, let's say we are selling fruit and we have three tables fruit, fruit_sold and fruit_orders
fruit
|---------------------|------------------|
| id | fruit |
|---------------------|------------------|
| 1 | Apples |
|---------------------|------------------|
| 2 | Oranges |
|---------------------|------------------|
| 3 | pears |
|---------------------|------------------|
fruit_sold
|---------------------|------------------|------------------|------------------|
| id | fruit_id | sold_per_day | day_sold |
|---------------------|------------------|------------------|------------------|
| 1 | 1 | 101 | 1585695600 |
|---------------------|------------------|------------------|------------------|
| 2 | 2 | 445 | 1585695600 |
|---------------------|------------------|------------------|------------------|
| 3 | 3 | 214 | 1585782000 |
|---------------------|------------------|------------------|------------------|
| 4 | 1 | 512 | 1585782000 |
|---------------------|------------------|------------------|------------------|
fruit_orders
|---------------------|------------------|------------------|
| id | arriving | fruit_id |
|---------------------|------------------|------------------|
| 1 | 1592607600 | 1 |
|---------------------|------------------|------------------|
| 2 | 1586905200 | 3 |
|---------------------|------------------|------------------|
| 3 | 1590534000 | 2 |
|---------------------|------------------|------------------|
| 4 | 1588287600 | 3 |
|---------------------|------------------|------------------|
| 5 | 1593126000 | 1 |
|---------------------|------------------|------------------|
| 6 | 1592607600 | 2 |
|---------------------|------------------|------------------|
So far I have
SELECT SUM(fruit_sold.sold_per_day) / 2 AS consumption, fruit.fruit
FROM fruit_sold
LEFT JOIN fruit
ON fruit_sold.fruit_id = fruit.id
GROUP BY fruit_sold.fruit_id
How would I also return the number of days until the stock runs out (taking into account arriving orders and their arrival dates) for each fruit?
We want to return the following:
|---------------------|------------------|------------------|------------------|
| id | fruit | consumption | days_until_gone | |
|---------------------|------------------|------------------|------------------|
| 1 | apples | 306.5 | 2 |
|---------------------|------------------|------------------|------------------|
| 2 | oranges | 222.5 | 16 |
|---------------------|------------------|------------------|------------------|
| 3 | pears | 107 | 3 |
|---------------------|------------------|------------------|------------------|
You can get the numbers per day using union all, aggregation, and window functions:
select fruit_id, day_sold, sum(sold_per_day), sum(orders),
sum(sum(sold_per_day - orders)) over (partition by fruit_id order by day_sold) as net
from ((select fruit_id, day_sold, sold_per_day, 0 as orders
from fruit_sold
) union all
(select fruit_id, as day_sold, 0 as sold_per_day, count(*) as orders
from fruit_sold
group by fruit_id, day_sold
)
) f
group by fruit_id, day_sold;
I'm not 100% how this applies to your sample data, but it seems to basically provide the information that you want.

Need the difference between two columns ' different in number of items ' in two different tables in MS Access

I need the difference between items i bought and items i sold, items i bought in this table
ID |ItemName| PriceOfUnit | NumberOfItems I bought |DateIBought|
1 | tea | 3 | 6 |15/11/2015 |
2 | coffee | 5 | 4 |16/11/2015 |
3 | tea | 4 | 10 |20/12/2015 |
4 | juice | 5 | 15 | 1/1/2016 |
5 | coffee | 3 | 5 | 15/3/2016 |
6 | water | 5 | 2 | 16/4/2016 |
and items I sold is in this table
ID |ItemName| PriceOfUnit | NumberOfItems I sold |DateIBought|
1 | coffee | 5 | 6 | 1/1/2016 |
2 | tea | 5 | 9 | 15/3/2016 |
3 | coffee | 4 | 2 | 20/4/2016 |
4 | juice | 5 | 11 | 1/1/2016 |
I need a query , SQL query OR union Query in MS Access to get this result ?
ID |ItemName| NumberOfItems I have |
1 | coffee | 1 |
2 | tea | 7 |
3 | juice | 4 |
4 | water | 2 |
How can I get this result ?
Where NumberOfItems I have = NumberOfItems I bought - NumberOfItems I sold
You didn't provide attribute names or table names and you spec'd two RDBMS products, so here is p-code for your solution:
q1:
SELECT ItemName, SUM(bought) as SumBought from tBought GROUP BY ItemName
q2:
SELECT ItemName, SUM(sold) as SumSold from tSold GROUP BY ItemName
q3:
SELECT q1.ItemName, (SumBought - SumSold) as difference from q1 inner join q2 on q1.ItemName = q2.ItemName

How to group MySQL query by multiple criterias?

Here's what I'm trying to achieve. I have this table:
Table 'Receipts':
Fruit |Receipt| Name
| No |
--------|-------|-------
Apple | 534 | Mike
Apple | 422 | Mike
Apple | 355 | Mike
Peach | 646 | Robert
Banana | 412 | Alex
Banana | 124 | Alex
Banana | 067 | Sam
Banana | 975 | Sam
Banana | 645 | Sam
And I want to display each unique combination, so each item every person has:
Apple | Mike
Peach | Robert
Banana | Alex
Banana | Sam
I can only manage to either group things by fruit or by name, no idea how I could get this done.
Can anybody help?
SELECT Fruit, Name FROM tableName
GROUP BY Fruit, Name
Or if you want to have a unique combination, you can even do it as
SELECT Fruit, Name
FROM mytable
GROUP BY concat(Fruit,'-', Name) //group the data based on unique word formed

Select users associated to Approved list/table using Ms Access 2003/2013 or Sql query

[Users]
ID | UserID | City | Phone
----+-----------+-----------+----------
1 | John | Rome | 12345
2 | Tom | Oslo | 12345
3 | Simon | Bogota | 12345
4 | Kurt | Tokyo | 12345
[Orders]
ID | UserID | OrderNr | OrderName
------------------------------------------------
1 | John | 1 | Apple
2 | John | 2 | Carrots
3 | John | 3 | Banana
4 | Tom | 3 | Banana
5 | Tom | 1 | Apple
6 | Tom | 8 | Raisins
7 | Simon | 3 | Banana
8 | Simon | 1 | Apple
9 | Kurt | 7 | Cucumber
Approved List
1 (Apple)
3 (Banana)
4 (Another order)
8 (Raisins)
Now i would like to select all Users who's orders only contains/matches my approved list.
John should be excluded in this case because he ordered Carrots which has OrderNr 2 that is not in my approved list.
If you want users who only have orders in the approved list, I would suggest conditional aggregation and a having clause:
select o.userid
from orders as o
group by o.userid
having sum(iif(o.OrderNr not in (1, 3, 4, 8), 1, 0)) = 0;
The having clause filters out users who have an "unapproved" product.

Mysql, storing multiple value in single column from another table

Bear with me, im really bad at explaining thing and i dont even know an appropriate title for this problem
Ok guys i have this problem
I already have one table name meal
+------+--------+-----------+---------+
| id | name | serving | price |
+------+--------+-----------+---------+
| 1 | soup1 | 2 person | 12.50 |
+------+--------+-----------+---------+
| 2 | soup2 | 2 person | 15.50 |
+------+--------+-----------+---------+
| 3 | soup3 | 2 person | 23.00 |
+------+--------+-----------+---------+
| 4 | drink1 | 2 person | 4.50 |
+------+--------+-----------+---------+
| 5 | drink2 | 2 person | 3.50 |
+------+--------+-----------+---------+
| 6 | drink3 | 2 person | 5.50 |
+------+--------+-----------+---------+
| 7 | frui1 | 2 person | 3.00 |
+------+--------+-----------+---------+
| 8 | fruit2 | 2 person | 3.50 |
+------+--------+-----------+---------+
| 9 | fruit3 | 2 person | 4.50 |
+------+--------+-----------+---------+
Ok now i want to allow admin to create a combo meal from this meal table
So that mean, a combo meal can have unlimited number amout of meal
Currently im puzzle how to store/link combo meal to the meal
I donw want to store something lke below
+------+--------------+-----------+-----------+
| id | combo_name | serving | meal_id |
+------+--------------+-----------+-----------+
| 1 | combo1 | 2 person | 1,4,7,9 |
+------+--------------+-----------+-----------+
| 2 | combo2 | 2 person | 2,5,8 |
+------+--------------+-----------+-----------+
| 4 | combo3 | 2 person | 3,5,6,9 |
+------+--------------+-----------+-----------+
Look at the meal_id column, i dont think that is a good way to store a data
Create a many-to-many link table:
combo_id meal_id
1 1
1 4
1 7
1 9
2 2
2 5
2 8
3 3
3 5
3 6
3 9
To select all meals for a given combo:
SELECT m.*
FROM combo_meal cm
JOIN meal m
ON m.id = cm.meal_id
WHERE cm.combo_id = 1
No. It's definitely not a good way to store data. You will be better with a combo_header table and a combo_details table.
combo_header will be something like:
+------+--------------+-----------+
| id | combo_name | serving |
+------+--------------+-----------+
| 1 | combo1 | 2 person |
+------+--------------+-----------+
| 2 | combo2 | 2 person |
+------+--------------+-----------+
| 4 | combo3 | 2 person |
+------+--------------+-----------+
And then, combo_details will be something like:
+------+-----------+
| id | meal_id |
+------+-----------+
| 1 | 1 |
+------+-----------+
| 1 | 4 |
+------+-----------+
| 1 | 7 |
+------+-----------+
| 1 | 9 |
+------+-----------+
... / you get the idea!
By the way, by using multiple values in a single column you are violating first normal form of relational databases.
The way I'm proposing will let you answer queries like get all name of the meals of combo1 very easy to resolve.
This is called a many-to-many relationship between meals and combo. A meal can be listed in multiple combos and a combos can contain multiple meals. You will need a link table (instead of the combo.meal_id field) that contains all possible meal-combo pairs.
In the end, you will have three tables:
meal (meal_id, serving, name)
combo (combo_id, serving, name)
meal_combo (autoid, meal_id, combo_id)
meal_combo.autoid is not strictly needed, it's just a general recommendation.
To list a combo with all it's meals in it:
SELECT meal.id, meal.name FROM comboINNER JOIN meal_combo ON meal_combo.combo_id = combo.id INNER JOIN meal ON meal.id = meal_combo.meal_id WHERE combo.id = 132
Google for 'many-to-many relationship' or 'database link table' for details.