I have a table called of 'orders' that records an order id for a meal, a person id for the person who ordered the meal and the meal (which can be 1, 2, or 3)
orders
oid | pid | meal
________________
1 | 1 | 2
2 | 1 | 3
3 | 3 | 1
4 | 5 | 2
5 | 5 | 2
6 | 5 | 1
I want to generate a result that will allow me to view the number of orders for each meal for each pid:
pid | meal1 | meal2 | meal3
____________________________
1 | 0 | 1 | 1
3 | 1 | 0 | 0
5 | 0 | 2 | 1
I am not an SQL expert, but I was thinking that I would first group the list by pid, then by meal. But how would I do the counting? I am truly lost.
Basically you need to first create multiple columns for the different meals using case when, then you can group by pid and sum it up
Select pid, sum(case when meal =1 then 1 else 0 end) as meal1,
sum(case when meal =2 then 1 else 0 end) as meal2,
sum(case when meal =3 then 1 else 0 end) as meal3
from Table
group by pid
Related
In MySQL, I have a table that holds the outcomes of rounds of a contest. This table has a result column that contains the values 'won' 'lost' or 'draw'. How can I group by the competitor and get the counts of specific values? The idea is to be able to sort competitors based on the number of wins and losses, and calculate scores within the database query.
So, my table is:
+--------------+---------+--------+
| CompetitorId | MatchId | Result |
+--------------+---------+--------+
| 1 | 1 | won |
| 2 | 1 | lost |
| 1 | 2 | won |
| 3 | 2 | lost |
+--------------+---------+--------+
The result I am trying to get is:
+--------------+------+--------+
| CompetitorId | Wins | Losses |
+--------------+------+--------+
| 1 | 2 | 0 |
| 2 | 0 | 1 |
| 3 | 0 | 1 |
+--------------+------+--------+
The query I tried was this:
SELECT CompetitorId, COUNT(result='won') AS wins, COUNT(result='lost') AS losses
FROM match_competitors
GROUP BY CompetitorId
You can use sum with a case inside, giving a value of 1 when is the column you need and 0 when is not:
SELECT CompetitorId, sum(case result
when 'won' then 1
else 0
end) as wins,
sum(case result
when 'lost' then 1
else 0
end) as losses
FROM match_competitors
GROUP BY CompetitorId
I have these 2 tables:
Table Users:
id | name
---------
1 | Joe
2 | Sara
3 | Michael
Table Sales:
id | product | user_id
------------------------
1 | Car | 2
2 | Truck | 3
3 | motorcycle| 1
4 | Car | 2
5 | Truck | 1
6 | Car | 3
7 | Car | 2
8 | Truck | 3
9 | Car | 2
10 | Car | 3
I want the following:
User Name | Car | Truck | Motorcycle
Joe | 0 | 1 | 1
Sara | 4 | 0 | 0
Michael | 2 | 2 | 0
Any help would be appreciated
--For a small number of products this works,
Select username
, Sum(case when product = 'Car' then 1 else 0 End) Cars
, Sum(case when product = 'Truck' then 1 else 0 End) Truck
, Sum(case when product = 'motorcycle' then 1 else 0 End) motorcycle
From Sales s join users u on s.userid = u.userid
group by username
SELECT Users.name,
SUM(Case
WHEN product='Car' then 1
ELSE 0
) AS Car,
SUM(Case
WHEN product='Truck' then 1
ELSE 0
) AS Truck ,
SUM(Case
WHEN product='Motorcycle' then 1
ELSE 0
) AS Motorcycle,
FROM Users
LEFT JOIN Sales ON Users.id = Sales.user_id
GROUP BY Users.name
SELECT
name as UserName ,
SUM(product= 'Car')AS Car,
SUM(product= 'Truck')AS Truck,
SUM(product= 'motorcycle') AS motorcycle
FROM Users join Sales
on Users.id = Sales.user_id
GROUP BY name
hope it helps but still this is a standard solution you should check pivot Tables.
I have a query which creates a crosstab. The results are a count of the txn_id for branda, and the count of txn_id for brandb.
The txn_id is NOT UNIQUE. This is an example of the transactions table.:
txn_id | nationality_id | sku | sales | units
1 | 1 | 1 | 20 | 2
1 | 1 | 2 | 15 | 1
2 | 4 | 1 | 20 | 2
3 | 2 | 1 | 10 | 1
4 | 3 | 2 | 15 | 1
5 | 4 | 1 | 10 | 1
There are 2 other tables (products) - (sku, brand, product name), and (nationalities) - (nationality_id, nationality).
I would like to add a third column which gets me the count of txn_id where BOTH brands are purchased
The output should be
nationality | branda | brandb | combined
1 | 1 | 1 | 1
2 | 1 | 0 | 0
3 | 0 | 1 | 0
4 | 2 | 0 | 0
Current query.
SELECT
nationalities.nationality,
COUNT((CASE brand WHEN 'branda' THEN txn_id ELSE NULL END)) AS branda,
COUNT((CASE brand WHEN 'brandb' THEN txn_id ELSE NULL END)) AS brandb
<I want my 3rd column here>
FROM
transaction_data
INNER JOIN
products USING (sku)
INNER JOIN
nationalities USING (nationality_id)
GROUP BY nationality
ORDER BY branda DESC
LIMIT 20;
I have tried using:
COUNT((CASE brand WHEN 'brandb' OR 'brandb' THEN txn_id ELSE NULL END)) AS combined - however this obviously returns too many (returns branda or brandb regardless of whether they were purchased together). I know I can't use AND, because obviously no single cell is going to be both branda AND brandb.
I have also tried using:
COUNT((CASE brand WHEN IN('branda', 'brandb') THEN txn_id ELSE NULL END)) AS combined - However this isn't valid syntax.
I feel that I should be using a HAVING clause, but I'm not sure how this would work in the column list.
I think you are going to need two levels of aggregation:
SELECT n.nationality,
sum(branda), sum(brandb), sum(branda * brandb)
FROM (SELECT t.txn_id, n.nationality,
MAX(CASE brand WHEN 'branda' THEN 1 ELSE 0 END) AS branda,
MAX(CASE brand WHEN 'brandb' THEN 1 ELSE 0 END) AS brandb
FROM transaction_data t INNER JOIN
products p
USING (sku) INNER JOIN
nationalities n
USING (nationality_id)
GROUP BY t.txn_id, n.nationality
) tn
GROUP BY n.nationality
ORDER BY max(txn_id) DESC
LIMIT 20;
I am trying to show one semesters aggregates in one column, the next semester's aggregates in the second column, and the third semesters aggregates in the third column. Also the real tables, I don't know how many status codes there are...
I have a semester table:
Id Semester
+----+----------+
| 1 Current |
| 2 Next |
| 3 2 Ahead |
+----+----------+
I have a simple project table:
Id Title Status termId
+----+--------+---------+--------+
| 1 A OK 1 |
| 2 B Bad 1 |
| 3 C OK 1 |
| 4 D Bad 2 |
| 5 E OK 2 |
| 6 F Bad 3 |
| 7 G OK 2 |
+----+--------+---------+--------+
This is the desired Output:
Status CurrentCount NextCount 2AheadCount
+---------+--------------+-----------+-------------+
| OK 2 1 0 |
| Bad 1 1 1 |
+---------+--------------+-----------+-------------+
What would you recommend I do to be able to achieve this?
You can use conditional aggregation with group by:
select status,
sum(case when termId = 1 then 1 else 0 end) CurrentCount,
sum(case when termId = 2 then 1 else 0 end) NextCount,
sum(case when termId = 3 then 1 else 0 end) 2AheadCount
from project
group by status
I have two tables that I'm attempting to retrieve specific information from (duh I know). The first table seasons is semi-static data storage and the second table users_cards is used to store user choices.
The result I am hoping to achieve would go through each season, assign a "card_total" = 10 for seasons 1-3 and 11 for each season moving forward. The result would look something similar to:
SEASON_ID | TOTAL |
------------ ------------
1 | 123
2 | 234
3 | 345
4 | 456
The abbreviated & pertinent columns / sample data is as follows:
# `seasons`:
ID | ACTIVE | COMPLETE |
---- ----------- ---------------
1 | 0 | 1
2 | 0 | 1
3 | 0 | 1
4 | 1 | 0
5 | 0 | 0
# `users_cards`
# DESC: this table can store up to 10 choices per user for seasons 1-3
# and up to 11 choices for every season thereafter.
USER_ID | SEASON_ID |
------------ ---------------
1 | 1
1 | 1
2 | 1
2 | 1
1 | 2
1 | 2
1 | 2
I've played around with a few variations of this query but nothing seems to be doing the trick. This query returns the total count for each season but it's not based off of the "card_total" I mentioned above.
SELECT
c.season_id AS season_id,
c.card_total AS card_total,
c.total AS total
FROM seasons s
INNER JOIN (
SELECT
uc.season_id,
COUNT(DISTINCT(user_id)) AS total,
CASE WHEN
uc.season_id = 1
OR uc.season_id = 2
OR uc.season_id = 3
THEN 10
ELSE 11
END AS card_total
FROM users_cards uc
GROUP BY uc.season_id
) AS c ON c.season_id = s.id
WHERE s.is_active = 1
OR s.is_complete = 1
Put SUM() around your CASE...END.