I want to add a survey to a website. And a good survey needs a reporting. Some basic reports are done. Now I want to put some cream on the coffee ...
The table with sample data:
mysql> select * from u001;
+----+----------+------------+-------+---------------------+
| id | drink | sex | age | date |
+----+----------+------------+-------+---------------------+
| 1 | Beer | m | 30-39 | 2012-10-17 23:17:52 |
| 2 | Milk | f | 10-19 | 2012-10-18 00:15:59 |
| 3 | Milk | f | 20-29 | 2012-10-18 23:33:07 |
| 4 | Tea | m | 30-39 | 2012-10-20 22:47:08 |
| 5 | Water | f | 20-29 | 2012-10-20 22:47:30 |
| 6 | Milk | m | 30-39 | 2012-10-20 22:51:22 |
+----+----------+------------+-------+---------------------+
6 rows in set (0.00 sec)
I want to get a result that counts how many women/men likes Tea/Beer/etc.
A desired result like this:
+-------+-----+---------+
| drink | sex | counted |
+-------+-----+---------+
| Beer | m | 1 |
| Milk | f | 2 |
| Tea | m | 1 |
| Water | f | 1 |
| Milk | m | 1 |
+-------+-----+---------+
Have anyone some suggestions or solutions?
Thanks in advance.
SELECT drink, sex, COUNT(id) counted
FROM u001
GROUP BY drink, sex
SQLFiddle Demo
select drink, sex, count(id) from u001 group by drink, sex
Related
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.
Let say I have 2 tables:
courses
| id | name | is_sort_by_borrower |
|----|--------------|---------------------|
| 1 | Comp Science | 1 |
| 2 | Biz Admin | 0 |
| 3 | Physics | 1 |
books
| id | title | borrower | last_borrow_date | course_id |
| --- | ------ | -------- | ---------------- | --------- |
| 1 | Book A | 523 | 11/12/19 12:33 | 1 |
| 2 | Book B | 423 | 11/15/19 12:33 | 1 |
| 3 | Book C | 401 | 10/22/19 12:33 | 1 |
There's a column is_sort_by_borrower in courses, I want to get a result like this
| course | book_title | borrower | last_borrow_date | is_sort_by_borrower |
|--------------|------------|----------|------------------|---------------------|
| Comp Science | Book A | 523 | 11/12/19 12:33 | 1 |
| Comp Science | Book B | 423 | 11/15/19 12:33 | 1 |
| Comp Science | Book C | 401 | 10/22/19 12:33 | 1 |
| Comp Science | Book D | 377 | 11/19/19 12:33 | 1 |
| Biz Admin | Book E | 122 | 11/20/19 12:33 | 0 |
| Biz Admin | Book F | 419 | 11/12/19 12:33 | 0 |
| Biz Admin | Book G | 65 | 10/18/19 12:33 | 0 |
| Physics | Book H | 446 | 8/31/19 12:33 | 1 |
| Physics | Book I | 398 | 11/2/19 12:33 | 1 |
| Physics | Book J | 376 | 9/30/19 12:33 | 1 |
| Physics | Book K | 249 | 10/11/19 12:33 | 1 |
Is it possible to sort the result some by borrower, some by last_borrow_date?
Yes, create another column in the SELECT and use CASE to populate it with the value you want, then sort by that. You can also use the CASE statement in the WHERE clause, depending on if you want the sorting column to show the result or not.
ref: MYSQL ORDER BY CASE Issue
ref: https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html
In your example:
SELECT
c.id, c.name, c.is_sort_by_borrower,
b.id, b.title, b.borrower, b.last_borrow_date
FROM
courses c
INNER JOIN
books b on b.course_id = c.id
ORDER BY
CASE
WHEN is_sort_by_borrower=1 THEN borrower
WHEN is_sort_by_borrower=0 THEN last_borrow_date
END ASC
The ORDER BY needs to look like:
ORDER BY course -- courses grouped together
, CASE WHEN is_sort_by_borrower = 1 THEN borrower END DESC
, CASE WHEN is_sort_by_borrower = 0 THEN last_borrow_date END DESC
Exactly one of the two columns will be NULL for a given course depending on the sort flag. You must not combine the two datatypes in same column otherwise result will be unpredictable.
this is my first time posting here. I don't seem to find the answer to my problem.
So... I'm arranging a DB for a school project, a cookbook that only shows recipes that can be made with existing elements from the "shelf".
These ingredients have to have an exact ingredients match.
user:
+---------------+------+----------+----------+
| email | name | lastname | password |
+---------------+------+----------+----------+
| pal#mail.com | John | Potato | password |
| they#mail.com | Mary | Carrot | password |
+---------------+------+----------+----------+
shelf:
+---------+------------+---------------+
| shelfID | ingredient | user |
+---------+------------+---------------+
| 1 | 1 | pal#mail.com |
| 2 | 2 | pal#mail.com |
| 3 | 3 | pal#mail.com |
| 4 | 4 | pal#mail.com |
| 5 | 10 | they#mail.com |
| 6 | 12 | they#mail.com |
+---------+------------+---------------+
This is my recipe_ingredient relationship table
recipe_ingredient:
+--------+------------+
| recipe | ingredient |
+--------+------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 4 |
| 1 | 10 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 2 | 4 |
| 3 | 2 |
| 3 | 3 |
| 3 | 15 |
+--------+------------+
I've tried this query:
SELECT
rec_ing.recipe, shf.ingredient, shf.user
FROM
recipes_ingredients AS rec_ing
INNER JOIN
shelf AS shf ON rec_ing.ingredient = shf.ingredient
INNER JOIN
users AS usr ON shf.user = usr.email
WHERE
usr.email = 'pal#mail.com'
that returns this table:
+--------+------------+--------------+
| recipe | ingredient | user |
+--------+------------+--------------+
| 1 | 1 | pal#mail.com |
| 1 | 2 | pal#mail.com |
| 1 | 4 | pal#mail.com |
| 2 | 1 | pal#mail.com |
| 2 | 2 | pal#mail.com |
| 2 | 3 | pal#mail.com |
| 2 | 4 | pal#mail.com |
| 3 | 2 | pal#mail.com |
| 3 | 3 | pal#mail.com |
+--------+------------+--------------+
Although it's true that the Recipe 1 contains ingredients from my shelf, it's also missing Ingredient 10
+--------+------------+
| recipe | ingredient |
+--------+------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 4 |
| 1 | 10 |
| ... | ... |
+--------+------------+
I'm trying to only get this kind of result set.
+--------+------------+
| recipe | ingredient |
+--------+------------+
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 2 | 4 |
+--------+------------+
Because Recipe 2 contains all elements from my shelf
I have been going around all day with this problem ... What could be missing?
This is a bit tricky, because you need to aggregate your current query by recipe, but you also need the original query to get back the full records. Sadly, MySQL does not support common table exprrssions or other features which could give us a less verbose query.
SELECT
rec_ing.recipe,
shf.ingredient,
shf.user
FROM recipes_ingredients AS rec_ing
INNER JOIN shelf AS shf
ON rec_ing.ingredient = shf.ingredient
INNER JOIN users AS usr
ON shf.user = usr.email
INNER JOIN
(
SELECT rec_ing.recipe
FROM recipes_ingredients AS rec_ing
INNER JOIN shelf AS shf
ON rec_ing.ingredient = shf.ingredient
LEFT JOIN users AS usr
ON shf.user = usr.email
WHERE
usr.email = 'pal#mail.com'
GROUP BY rec_ing.recipe
HAVING COUNT(usr.email) = COUNT(*)
) t
ON rec_ing.recipe = t.recipe
WHERE
usr.email = 'pal#mail.com'
The basic strategy here is to just do one additional join to a subquery which identifies all recipes where every ingredient belongs to a given user. The critical part is the following:
HAVING COUNT(usr.email) = COUNT(*)
This checks that the total number of rows for a given recipe matches the number of rows which have been assigned to a given user.
I have the following tables below.
athletes
+------------+-----------------+---------------+-------------------------+
| idATHLETES | ATHLETENAME | TEAMS_idTEAMS | TEAMS_COUNTRY_idCOUNTRY |
+------------+-----------------+---------------+-------------------------+
| JG | JUSTIN GATLIN | USA-TF-MEN | USA |
| MS | MARIA SHARAPOVA | RUS-WTA | RUS |
| SW | SERENA WILLIAMS | USA-WTA | USA |
| UB | USAIN BOLT | JAM-TF-MEN | JAM |
| VW | VENUS WILLIAMS | USA-WTA | USA |
+------------+-----------------+---------------+-------------------------+
EVENTS
+------------+---------------+---------------------+------------------------+----------------------------------+
| idEVENTS | EVENTNAME | ATHLETES_idATHLETES | ATHLETES_TEAMS_idTEAMS | ATHLETES_TEAMS_COUNTRY_idCOUNTRY |
+------------+---------------+---------------------+------------------------+----------------------------------+
| ATH | ATHLETICS | JG | USA-TF-MEN | USA |
| ATH | ATHLETICS | UB | JAM-TF-MEN | JAM |
| TEN | TENNIS | MS | RUS-WTA | RUS |
| TEN | TENNIS | VW | USA-WTA | USA |
| TEN-DOUBLE | TENNIS DOUBLE | SW | USA-WTA | USA |
| TEN-DOUBLE | TENNIS DOUBLE | VW | USA-WTA | USA |
+------------+---------------+---------------------+------------------------+----------------------------------+
RESULTS
+-----------+-------------+--------+-----------------+----------------------------+-------------------------------+-----------------------------------------+
| idRESULTS | STATUS | MEDALS | EVENTS_idEVENTS | EVENTS_ATHLETES_idATHLETES | EVENTS_ATHLETES_TEAMS_idTEAMS | EVENTS_ATHLETES_TEAMS_COUNTRY_idCOUNTRY |
+-----------+-------------+--------+-----------------+----------------------------+-------------------------------+-----------------------------------------+
| results1 | DID-NOT-WIN | SILVER | TEN | MS | RUS-WTA | RUS |
| results1 | WON | GOLD | TEN | VW | USA-WTA | USA |
| results2 | DID-NOT-WIN | BRONZE | ATH | JG | USA-TF-MEN | USA |
| results2 | WON | GOLD | ATH | UB | JAM-TF-MEN | JAM |
| results3 | WON | GOLD | TEN-DOUBLE | SW | USA-WTA | USA |
| results3 | WON | GOLD | TEN-DOUBLE | VW | USA-WTA | USA |
+-----------+-------------+--------+-----------------+----------------------------+-------------------------------+-----------------------------------------+
How can I get a list Athletes who participate in more than one Event
and won at least one of them
and won none of them
I have come out with this code below but this returns the wrong output ?
SELECT idATHLETES, ATHLETENAME, EVENTNAME FROM athletes
JOIN EVENTS ON idATHLETES = ATHLETES_idATHLETES
JOIN RESULTS ON events.ATHLETES_idATHLETES = RESULTS.EVENTS_ATHLETES_idATHLETES
WHERE idEVENTS >=2 AND STATUS = 'WON'
Athletes who participated in more than one Event and won at least one of them:
select a.idATHLETES as id,a.ATHLETENAME as Name,count(*) as evtCount,
SUM(CASE WHEN r.STATUS = 'WON' THEN 1 ELSE 0 END) as victoryCount
from athletes a
join EVENTS e
on e.ATHLETES_idATHLETES = a.idATHLETES and e.ATHLETES_TEAMS_idTEAMS = a.TEAMS_idTEAMS and e.ATHLETES_TEAMS_COUNTRY_idCOUNTRY = a.TEAMS_COUNTRY_idCOUNTRY
join RESULTS r
on r.EVENTS_idEVENTS=e.idEVENTS and r.EVENTS_ATHLETES_idATHLETES=e.ATHLETES_idATHLETES -- etc
group by a.idATHLETES,a.ATHLETENAME
having evtCount>1 and victoryCount>0
order by a.idATHLETES,a.ATHLETENAME;
Results:
+----+----------------+----------+--------------+
| id | Name | evtCount | victoryCount |
+----+----------------+----------+--------------+
| VW | VENUS WILLIAMS | 2 | 2 |
+----+----------------+----------+--------------+
Athletes who participated in more than one Event and won none:
select a.idATHLETES as id,a.ATHLETENAME as Name,count(*) as evtCount,
SUM(CASE WHEN r.STATUS = 'WON' THEN 1 ELSE 0 END) as victoryCount
from athletes a
join EVENTS e
on e.ATHLETES_idATHLETES = a.idATHLETES and e.ATHLETES_TEAMS_idTEAMS = a.TEAMS_idTEAMS and e.ATHLETES_TEAMS_COUNTRY_idCOUNTRY = a.TEAMS_COUNTRY_idCOUNTRY
join RESULTS r
on r.EVENTS_idEVENTS=e.idEVENTS and r.EVENTS_ATHLETES_idATHLETES=e.ATHLETES_idATHLETES -- etc
group by a.idATHLETES,a.ATHLETENAME
having evtCount>1 and victoryCount=0
order by a.idATHLETES,a.ATHLETENAME;
Results:
no rows returned, you lack data for that
Notes
This is just a group by with having, and conditional aggregation (plus really messed up column names) :p
You can use having to get the records where there are at least two events and status = 'won' at least once.
SELECT idATHLETES, ATHLETENAME, EVENTNAME FROM athletes
JOIN EVENTS ON idATHLETES = ATHLETES_idATHLETES
JOIN RESULTS ON events.ATHLETES_idATHLETES = RESULTS.EVENTS_ATHLETES_idATHLETES AND RESULTS.Status = 'WON'
HAVING COUNT(idEVENTS) >=2 AND COUNT(STATUS) >= 1
i have two tables: invoice and orderlist
Invoice contains
+----------------+---------------+-------------+------------+
| orderInvoice | orderCustomer | orderTime | orderTotal |
+----------------+---------------+-------------+------------+
| 00001 | Nick | 2012-11-29 | 30.00 |
| 00002 | Andrew | 2012-11-29 | 15.00 |
| 00003 | West | 2012-11-29 | 80.00 |
+----------------+---------------+-------------+------------+
orderlist contains
+----------------+------------------+------+--------+
| orderInvoice | item | size | Qty | price |
+----------------+------------------+------+--------+
| 00001 | Coke | Can | 20 | 0.50 |
| 00001 | Coke | Bottle | 10 | 2.00 |
| 00002 | Sprite | Can | 30 | 0.50 |
| 00003 | Coke | Bottle | 40 | 2.00 |
+----------------+------------------+------+--------+
i want to output like this:
+---------------------------------------------------+
| Most Popular Soda |
+---------------------------------------------------+
| Coke Bottle 50 |
| Sprite Can 30 |
| Coke Can 20 |
+---------------------------------------------------+
| 2012-11-29 |
+---------------------------------------------------+
I tried to query it with concat() as ITEM and then count(ITEM) . it looks like i can use them together in a single query.
------------UPDATE----------------
Thank you guys for post the answers. I figured it out the answer(can't do it without your guys help). I will leave the answer there in case others might looking for it as well
SELECT
CONCAT(
orderlist.item,
orderlist.size
) AS item,
orderlist.orderInvoice,
SUM(orderlist.Qty) AS Qty
FROM
orderlist
INNER JOIN invoice ON nvoice.orderInvoice = orderlist.orderInvoice
WHERE
Invoice.orderTime = '2012-11-29'
GROUP BY
item
ORDER BY
Qty DESC
try this
select item,sum(qty) as quantity from orderlist group by item;
Try this:
Select item, size, SUM(qty) quantity
from
orderlist
group by item, size
order by quantity desc