Mysql - Counting different values of the same field - mysql

I have the following table:
Table games
+----+----------+------+---------------------+
| id | name | win | date |
+----+----------+------+---------------------+
| 1 | Fulano | Y | 2014-01-01 00:00:00 |
| 2 | Fulano | Y | 2014-01-01 00:00:00 |
| 3 | Fulano | Y | 2014-01-02 00:00:00 |
| 4 | Fulano | Y | 2014-01-03 00:00:00 |
| 5 | Fulano | N | 2014-01-03 00:00:00 |
| 6 | Beltrano | N | 2014-01-01 00:00:00 |
| 7 | Beltrano | N | 2014-01-01 00:00:00 |
| 8 | Beltrano | N | 2014-01-02 00:00:00 |
| 9 | Beltrano | Y | 2014-01-03 00:00:00 |
| 10 | Cicrano | Y | 2014-01-03 00:00:00 |
| 11 | Cicrano | N | 2014-01-03 00:00:00 |
+----+----------+------+---------------------+
I would like to do something like:
SELECT name, count(win='Y') AS wins, count(win='N') AS losses FROM games GROUP BY name;
Obviously I get an unwanted response due to the "count" does not recognize the command that I invented:
+----------+----------+----------+
| name | wins | losses |
+----------+----------+----------+
| Beltrano | 4 | 4 |
| Cicrano | 2 | 2 |
| Fulano | 5 | 5 |
+----------+----------+----------+
Could someone help get the correct answer?

SELECT
name,
SUM( win = 'Y' ) AS wins,
SUM( win = 'N' ) AS losses
FROM games
GROUP BY name;

Related

"Looping" the same SQL query for all entries grouped by date

I have a table like this:
+------------+-----------+------+----+
| date | player_id | rank | hp |
+------------+-----------+------+----+
| 2021-01-01 | 1 | 1 | 39 |
| 2021-01-01 | 5 | 2 | 20 |
| 2021-01-01 | 2 | 3 | 12 |
| 2021-01-01 | 3 | 4 | 48 |
| 2021-01-01 | 4 | 5 | 25 |
| 2021-01-02 | 1 | 2 | 42 |
| 2021-01-02 | 2 | 1 | 38 |
| 2021-01-02 | 3 | 4 | 21 |
| 2021-01-02 | 4 | 3 | 35 |
| 2021-01-02 | 5 | 5 | 28 |
| 2021-01-03 | 1 | 5 | 38 |
| 2021-01-03 | 3 | 2 | 31 |
| 2021-01-03 | 2 | 3 | 26 |
| 2021-01-03 | 4 | 4 | 22 |
| 2021-01-03 | 5 | 1 | 19 |
+------------+-----------+------+----+
When I use the following SQL code:
SELECT * FROM
(SELECT * FROM `players` WHERE date='2021-01-01' ORDER BY rank ASC LIMIT 3) highest_rank
ORDER BY hp DESC LIMIT 2
The result will be this:
+------------+-----------+------+----+
| date | player_id | rank | hp |
+------------+-----------+------+----+
| 2021-01-01 | 1 | 1 | 39 |
| 2021-01-01 | 5 | 2 | 20 |
+------------+-----------+------+----+
My problem is the result is only for date='2021-01-01'. I want to do this for every day in the database. Ultimately, I want the result to look like this:
+------------+-----------+------+----+
| date | player_id | rank | hp |
+------------+-----------+------+----+
| 2021-01-01 | 1 | 1 | 39 |
| 2021-01-01 | 5 | 2 | 20 |
| 2021-01-02 | 1 | 2 | 42 |
| 2021-01-02 | 2 | 1 | 38 |
| 2021-01-03 | 3 | 2 | 31 |
| 2021-01-03 | 2 | 3 | 26 |
+------------+-----------+------+----+
How can this be done? I'm using MySQL/MariaDB if that makes any difference.
Problem solved. Credit goes to sticky bit in the comment section that provided a solution that almost worked. He retracted the suggestion because it wasn't the final solution, I think. But I tinkered with it and got it to work. Thank you, sticky bit!
For anyone interested in the solution:
SELECT date, player_id, rank, hp
FROM
(
SELECT *,
row_number() OVER (PARTITION BY date
ORDER BY hp DESC) h
FROM
(
SELECT *,
row_number() OVER (PARTITION BY date
ORDER BY rank ASC) r
FROM players
) x
WHERE r<=3
) y
WHERE h<=2

Mysql Row To Column Select Specific Data

I have column user and rating.
SELECT rating.idUser, user.nmUser, rating.idBengkel, rating.nilai FROM `rating`
JOIN user on rating.idUser = user.idUser
WHERE rating.idBengkel=1 or rating.idBengkel=2
Result :
+--------+---------------------------+-----------+-------+
| idUser | nmUser | idBengkel | nilai |
+--------+---------------------------+-----------+-------+
| 10 | Hudson mas77 | 1 | 5 |
| 11 | Vina Nurfadzilah | 1 | 5 |
| 12 | Angelica Amartya | 1 | 5 |
| 15 | Syahrul K | 1 | 4 |
| 27 | Ashar Murdihastomo | 1 | 5 |
| 28 | Eril Obeit Choiri | 1 | 2 |
| 29 | Ariyadi | 1 | 3 |
| 30 | Robertus Dwian Augusta | 1 | 4 |
| 31 | Irfan Setiaji | 1 | 4 |
| 33 | Baby Ayuna | 1 | 5 |
| 9 | Nur k hamid | 2 | 5 |
| 10 | Hudson mas77 | 2 | 5 |
| 13 | Yuana Putra | 2 | 4 |
| 14 | Nanda Aulia Irza Ramadhan | 2 | 4 |
| 26 | taufiq rahman | 2 | 5 |
| 27 | Ashar Murdihastomo | 2 | 5 |
| 28 | Eril Obeit Choiri | 2 | 5 |
| 30 | Robertus Dwian Augusta | 2 | 4 |
| 44 | halim budiono | 2 | 1 |
+--------+---------------------------+-----------+-------+
When i try to get similar records using this query
SELECT rating.idUser, user.nmUser FROM rating
JOIN user
ON rating.idUser = user.idUser
WHERE rating.idBengkel = 1 and rating.idUser
IN (SELECT rating.idUser from rating WHERE rating.idBengkel = 2)
ORDER by idUser
Result :
+-----------+------------------------+
| idUser | nmUser |
+-----------+------------------------+
| 10 | Hudson mas77 |
| 27 | Ashar Murdihastomo |
| 28 | Eril Obeit Choiri |
| 30 | Robertus Dwian Augusta |
+-----------+------------------------+
The result work fine, but I want show column 'nilai' as ItemX and ItemY. Those are user similar data. In this case I have 4 similar user who rate on idBengkel=1 and idBengkel=2 as the results above. I want it like the table below.
+--------+------------------------+-------+-------+
| idUser | nmUser | ItemX | ItemY |
+--------+------------------------+-------+-------+
| 10 | Hudson mas77 | 5 | 5 |
| 27 | Ashar Murdihastomo | 5 | 5 |
| 28 | Eril Obeit Choiri | 2 | 5 |
| 30 | Robertus Dwian Augusta | 4 | 4 |
+--------+------------------------+-------+-------+
I need solution for this and i was trying with this solution in https://stackoverflow.com/a/7976379/12396302 but it resulting more than one row. Please help me, I cant implement that query's solution. Regards!
I think you need below query -
SELECT rating.idUser,
user.nmUser,
MAX(CASE WHEN rating.idBengkel = 1 THEN rating.nilai END) ItemX,
MAX(CASE WHEN rating.idBengkel = 2 THEN rating.nilai END) ItemY,
FROM `rating`
JOIN user on rating.idUser = user.idUser
WHERE rating.idBengkel IN (1, 2)
GROUP BY rating.idUser,
user.nmUser

MYSQL: Display one query from a select statement from two unrelated tables

I'm trying to display the sum of monthly revenue from different unrelated tables, Where i display the budgeted against the actual usage
I have two tables Planned Budget and actual budget, with with similar columns but different data, in a query i want retrieve the sum of budget and group it Yearly and monthly.
Planned Budget table
+-----+-------+-------------+-------------+
| uid | codes | opca_budget | date_period |
+-----+-------+-------------+-------------+
| 10 | 3210 | 3000 | 2018-03-01 |
| 17 | 3355 | 3000 | 2018-03-01 |
| 33 | 3210 | 4000 | 2018-04-01 |
| 40 | 3355 | 4000 | 2018-04-01 |
| 56 | 3210 | 5000 | 2018-05-01 |
| 63 | 3355 | 5000 | 2018-05-01 |
| 79 | 3210 | 6000 | 2018-06-01 |
| 86 | 3355 | 6000 | 2018-06-01 |
| 109 | 3355 | 45000 | 2018-07-01 |
Actual Budget
+-----+-------+-------------+---------------------+
| uid | codes | opca_budget | date_period |
+-----+-------+-------------+---------------------+
| 10 | 3210 | 6500 | 2018-03-01 00:00:00 |
| 17 | 3355 | 6500 | 2018-03-01 00:00:00 |
| 18 | 3120 | 6500 | 2018-03-01 00:00:00 |
| 33 | 3210 | 7500 | 2018-04-01 00:00:00 |
| 40 | 3355 | 7500 | 2018-04-01 00:00:00 |
| 41 | 3120 | 7500 | 2018-04-01 00:00:00 |
| 56 | 3210 | 8500 | 2018-05-01 00:00:00 |
| 63 | 3355 | 8500 | 2018-05-01 00:00:00 |
| 64 | 3120 | 8500 | 2018-05-01 00:00:00 |
I tried to combine them horizontally, But i get wrong results
SELECT YEAR(c.date_period)
, MONTH(c.date_period)
, SUM(c.opca_budget) MonthlyBudget
, SUM(a.opca_budget) MonthlyUsage
FROM opexcapex c
LEFT
JOIN opxcpx_actuals a
ON YEAR(c.date_period) = YEAR(a.date_period)
AND MONTH(c.date_period) = MONTH(a.date_period)
WHERE c.date_period BETWEEN '2018-03-01' AND '2019-02-29'
GROUP
BY YEAR(c.date_period)
, MONTH(c.date_period);
+------+-------+---------------+--------------+
| Year | Month | MonthlyBudget | MonthlyUsage |
+------+-------+---------------+--------------+
| 2018 | 3 | 168000 | 364000 |
| 2018 | 4 | 224000 | 420000 |
| 2018 | 5 | 280000 | 476000 |
| 2018 | 6 | 336000 | 532000 |
| 2018 | 7 | 2520000 | 588000 |
| 2018 | 8 | 576000 | 367200 |
| 2018 | 9 | 3240000 | 367200 |
| 2018 | 10 | 720000 | 252000 |
| 2018 | 11 | 792000 | 1807200 |
| 2018 | 12 | 2583000 | 1323000 |
| 2019 | 1 | 9000 | NULL |
| 2019 | 2 | 36000 | NULL |
+------+-------+---------------+--------------+
I expect to get results like this:
+-----------+-------------+---------------+--------------+
| BudgtYear | BudgetMonth | MonthlyBudget | MonthlyUsage |
+-----------+-------------+---------------+--------------+
| 2018 | 3 | 24000 | 45500 |
| 2018 | 4 | 32000 | 52500 |
| 2018 | 5 | 40000 | 59500 |
| 2018 | 6 | 48000 | 66500 |
| 2018 | 7 | 360000 | 73500 |
| 2018 | 8 | 72000 | 40800 |
| 2018 | 9 | 405000 | 40800 |
| 2018 | 10 | 90000 | 28000 |
| 2018 | 11 | 99000 | 200800 |
| 2018 | 12 | 369000 | 147000 |
| 2019 | 1 | 9000 | |
| 2019 | 2 | 36000 | |
+-----------+-------------+---------------+--------------+
You want to do a UNION ALL as a sub-query and then calculate the sum on the value from that sub-query, notice also that I use two amount columns in the union but one is always null, this is to have the two selects return the same number of columns but separated values
SELECT YEAR(date_period) as year, MONTH(date_period) as month, SUM(mbudget) AS MonthlyBudget, SUM(musage) as MonthlyUsage
FROM (SELECT date_period, opca_budget mbudget, null musage
FROM opexcapex
UNION ALL
SELECT date_period, null, opca_budget
FROM opxcpx_actuals
) sq
WHERE date_period BETWEEN '2018-03-01' AND '2019-02-29'
GROUP BY year, month
You should be able to UNION the 2 tables first, then SELECT from the resulting data, something like this (Updated query) :-
SELECT YEAR(date_period), MONTH(date_period), MonthlyBudget, MonthlyUsage
FROM
(SELECT date_period, opca_budget as MonthlyBudget, 0 as MonthlyUsage FROM
opexcapex
UNION
SELECT date_period, 0 as MonthlyBudget, opca_budget as MonthlyUsage FROM
opxcpx_actuals) T1
WHERE date_period BETWEEN '2018-03-01' AND '2019-02-29'
GROUP BY YEAR(date_period), MONTH(date_period);

MySQL: Get everyday incremental data

I want to fetch the data from Table based on date but in an incremental way.
Suppose I have data like this which is grouped by date
| DATE | Count |
| 2015-06-23 | 10 |
| 2015-06-24 | 8 |
| 2015-06-25 | 6 |
| 2015-06-26 | 3 |
| 2015-06-27 | 2 |
| 2015-06-29 | 2 |
| 2015-06-30 | 3 |
| 2015-07-01 | 1 |
| 2015-07-02 | 3 |
| 2015-07-03 | 4 |
So the result should come like this
| DATE | Count| Sum|
| 2015-06-23 | 10 | 10 |
| 2015-06-24 | 8 | 18 |
| 2015-06-25 | 6 | 24 |
| 2015-06-26 | 3 | 27 |
| 2015-06-27 | 2 | 29 |
| 2015-06-29 | 2 | 31 |
| 2015-06-30 | 3 | 34 |
| 2015-07-01 | 1 | 35 |
| 2015-07-02 | 3 | 38 |
| 2015-07-03 | 4 | 42 |
You would join every other previous date on that date, and then sum the count on that
If you give me your table structure, I can make it run.
id, name, date_joined
SELECT counts.theCount, sum(counts.theCount), table.date_joined
FROM yourTable
LEFT JOIN
(SELECT count(*) as theCount, table.date_joined
FROM yourTable
GROUP BY table.date_joined
) as counts
ON
yourTable.date_joined> counts.date_joined
GROUP BY yourTable.date_joined

MySQL SUM() returning spurious (?) values

Despite spending an hour on this, the solution is eluding me still. I have a complex-ish query that is returning incorrect data for the SUM(). Yet, when I strip it down to the barest form, it outputs the correct data. But why and fix, I cannot figure out.
The Problem
SELECT po.*, SUM( poo.material_qty ) AS total_items_ordered, suppliers.supplier_name
FROM `purchase_orders` po
LEFT JOIN purchase_orders_items poo ON poo.poid = po.poid
LEFT JOIN suppliers ON suppliers.supplier_id = po.supplier_id
LEFT JOIN materials_batch mb ON mb.purchase_order_no = po.poid
WHERE po_status NOT
IN (
'Fulfilled', 'Cancelled'
)
AND batch_status NOT
IN (
'Arrived', 'Cancelled', 'Refused', 'Missing', 'Damaged', 'Completed'
)
GROUP BY po.poid
ORDER BY date_expected ASC
Provides wildly incorrect data for 'total_items_ordered'.
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
| poid | date_raised | date_expected | supplier_id | job_id | job_item_id | ref_no | sub_total | VAT | total | userid | DN | manual | po_status | total_items_ordered | supplier_name |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
| 15571 | 2014-06-24 13:32:55 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 14850.10 | 2970.02 | 17820.12 | 1 | | N | Raised | 545 | John Parker & Son Ltd |
| 15572 | 2014-06-24 13:33:26 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 997.80 | 199.56 | 1197.36 | 1 | | N | Raised | 80 | John Parker & Son Ltd |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
2 rows in set (0.00 sec)
And yet, when I strip all the complexities out of the query and run the raw SUM(), the value is correct:
mysql> SELECT poid, SUM(material_qty) AS total_items_ordered FROM `purchase_orders_items` GROUP BY poid;
+-------+---------------------+
| poid | total_items_ordered |
+-------+---------------------+
| 15571 | 109 |
| 15572 | 20 |
+-------+---------------------+
2 rows in set (0.00 sec)
Can anyone shed any light on where I'm going wrong here?? I've included all the test table content below just in case you can spot something I've missed. Thank you!
Data Example
mysql> SELECT * FROM purchase_orders;
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
| poid | date_raised | date_expected | supplier_id | job_id | job_item_id | ref_no | sub_total | VAT | total | userid | DN | manual | po_status |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
| 15571 | 2014-06-24 13:32:55 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 14850.10 | 2970.02 | 17820.12 | 1 | | N | Raised |
| 15572 | 2014-06-24 13:33:26 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 997.80 | 199.56 | 1197.36 | 1 | | N | Raised |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM purchase_orders_items;
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
| poi_id | poid | material_id | material_qty | material_price | material_sku | material_name |
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
| 1 | 15571 | 2 | 3 | 100.00 | PKS275282 | 406x140 White Universal Beam (S355) |
| 2 | 15571 | 5 | 10 | 17.40 | 118-64-44 | Test Item (S275) |
| 3 | 15571 | 8 | 1 | 9984.50 | 113-64-21 | A really really really big universal beam (S355) |
| 4 | 15571 | 9 | 77 | 10.00 | 12345 | A thing |
| 5 | 15571 | 10 | 18 | 201.20 | 12-34-56 | 102x230 Narrow Beam (S355) |
| 6 | 15572 | 2 | 6 | 100.00 | PKS275282 | 406x140 White Universal Beam (S355) |
| 7 | 15572 | 5 | 9 | 17.40 | 118-64-44 | Test Item (S275) |
| 8 | 15572 | 9 | 4 | 10.00 | 12345 | A thing |
| 9 | 15572 | 10 | 1 | 201.20 | 12-34-56 | 102x230 Narrow Beam (S355) |
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
9 rows in set (0.00 sec)
mysql> SELECT * FROM suppliers;
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
| supplier_id | supplier_name | supplier_telephone | supplier_fax | supplier_added_date | supplier_added_by | supplier_last_updated | supplier_last_updated_by | supplier_assessed | supplier_approved_by |
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
| 1 | John Parker & Son Ltd | 01227 783333 | 0800 521932 | 2014-05-04 15:57:43 | 1 | 2014-06-05 16:38:23 | 1 | 2014-05-04 15:57:43 | 2 |
| 2 | Superior Glass Ltd. | 01825 764766 | 01825 767699 | 2014-05-04 17:48:38 | 1 | 2014-06-04 20:14:16 | 1 | 2014-05-04 17:48:38 | 3 |
| 3 | DTS Origins Ltd. | 01283 3283029 | 01928 303494 | 2014-05-04 17:51:57 | 1 | 2014-05-04 17:53:08 | 1 | 2014-05-04 17:51:57 | 2 |
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM materials_batch;
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+
| material_batch_id | poiid | rcvd_date | purchase_order_no | delivery_note_no | qty | rcvd_by | dn_scanned | material_id | supplier_id | batch_status |
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+
| 1 | 1 | 0000-00-00 00:00:00 | 15571 | | 3 | 0 | No | 2 | 1 | Ordered |
| 2 | 2 | 0000-00-00 00:00:00 | 15571 | | 10 | 0 | No | 5 | 1 | Ordered |
| 3 | 3 | 0000-00-00 00:00:00 | 15571 | | 1 | 0 | No | 8 | 1 | Ordered |
| 4 | 4 | 0000-00-00 00:00:00 | 15571 | | 77 | 0 | No | 9 | 1 | Ordered |
| 5 | 5 | 0000-00-00 00:00:00 | 15571 | | 18 | 0 | No | 10 | 1 | Ordered |
| 6 | 6 | 0000-00-00 00:00:00 | 15572 | | 6 | 0 | No | 2 | 1 | Ordered |
| 7 | 7 | 0000-00-00 00:00:00 | 15572 | | 9 | 0 | No | 5 | 1 | Ordered |
| 8 | 8 | 0000-00-00 00:00:00 | 15572 | | 4 | 0 | No | 9 | 1 | Ordered |
| 9 | 9 | 0000-00-00 00:00:00 | 15572 | | 1 | 0 | No | 10 | 1 | Ordered |
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+
The reason for the wrong results should be clear when you leave out the GROUP BY from your query. For each table you JOIN, the number of returned rows is multiplied by the number of rows found by the JOIN.
As the materials_batch table contains multiple entries per order, the resulting total_items_ordered is multiplied by 5 for order number 15571, and its multiplied by 4 for order number 15572.
Try the following:
SELECT
po.*,
(
SELECT SUM(poo.material_qty)
FROM purchase_orders_items poo
WHERE poo.poid = po.poid
) AS total_items_ordered,
suppliers.supplier_name
FROM `purchase_orders` po
LEFT JOIN suppliers ON suppliers.supplier_id = po.supplier_id
LEFT JOIN materials_batch mb ON mb.purchase_order_no = po.poid
WHERE po_status NOT
IN (
'Fulfilled', 'Cancelled'
)
AND batch_status NOT
IN (
'Arrived', 'Cancelled', 'Refused', 'Missing', 'Damaged', 'Completed'
)
GROUP BY po.poid
ORDER BY date_expected ASC