I have the following data in an MySQL database:
User_ID | Film | Choice
Where choice is either 1 or 0. I would like to create a google chart with the percentage choice (1s) after each film. I can produce this in excel as below:
Is there a way to produce a result which has these running totals, without creating a new column in the table? (similar to SUM)
First row should be 1 but set to 0 just to make the graph look better!
Assuming #fancyPants is right (ususally is), then you can also write that this way (slightly simpler and less scalable)...
SELECT x.*
, SUM(y.choice)/COUNT(*) * 100 pct
FROM film_choice x
JOIN film_choice y
ON y.film <= x.film
GROUP
BY x.film;
The first row should be 100%, right? 1 vote, 1 yes equals 100%
create table runningp(id int auto_increment primary key, choice tinyint);
insert into runningp(choice) values (1),(0),(0),(1),(1),(0),(1),(1),(0),(0);
select r.*, #p:=#p+choice, #t:=#t+1, #p/#t as yes
from runningp r,
(select #p:=0, #t:=0) v
order by id;
+----+--------+---------------+----------+--------+
| id | choice | #p:=#p+choice | #t:=#t+1 | yes |
+----+--------+---------------+----------+--------+
| 1 | 1 | 1 | 1 | 1.0000 |
| 2 | 0 | 1 | 2 | 0.5000 |
| 3 | 0 | 1 | 3 | 0.3333 |
| 4 | 1 | 2 | 4 | 0.5000 |
| 5 | 1 | 3 | 5 | 0.6000 |
| 6 | 0 | 3 | 6 | 0.5000 |
| 7 | 1 | 4 | 7 | 0.5714 |
| 8 | 1 | 5 | 8 | 0.6250 |
| 9 | 0 | 5 | 9 | 0.5556 |
| 10 | 0 | 5 | 10 | 0.5000 |
+----+--------+---------------+----------+--------+
To just select what you need:
select id, choice, yes from (
select r.*, #p:=#p+choice, #t:=#t+1, #p/#t as yes
from runningp r,
(select #p:=0, #t:=0) v
order by id
) sq
order by id;
+----+--------+--------+
| id | choice | yes |
+----+--------+--------+
| 1 | 1 | 1.0000 |
| 2 | 0 | 0.5000 |
| 3 | 0 | 0.3333 |
| 4 | 1 | 0.5000 |
| 5 | 1 | 0.6000 |
| 6 | 0 | 0.5000 |
| 7 | 1 | 0.5714 |
| 8 | 1 | 0.6250 |
| 9 | 0 | 0.5556 |
| 10 | 0 | 0.5000 |
+----+--------+--------+
10 rows in set (0.00 sec)
Related
MariaDB 10.1.18
Table P (id int AUTO_INCREMENT, rownum int, code int, s int, PRIMARY KEY(id));
select id, rownum, code, s from P order by id;
+----+--------+------+------+
| id | rownum | code | s |
+----+--------+------+------+
| 1 | 1 | 5 | 1 |
| 2 | 2 | 5 | 1 |
| 3 | 3 | 5 | 1 |
| 4 | 4 | 5 | 1 |
| 5 | 5 | 5 | 1 |
| 6 | 6 | 7 | 1 |
| 7 | 7 | 7 | 1 |
| 8 | 8 | 7 | 1 |
| 9 | 9 | 7 | 1 |
| 10 | 10 | 7 | 1 |
+----+--------+------+------+
Issue: the following 2 queries are very similar: 1st query join on id, 2nd join on rownum; the id and rownum columns are having the same values (see table above), but the query result is different in calculated column N:
Query 1: join on id column
SELECT P.id, P.rownum, P2.s,
IF(P2.s IS NULL, #val:=#val+1, #val) as N
FROM P CROSS JOIN (SELECT #val:=0) init
LEFT JOIN P P2
ON (P.id+1=P2.id AND P.s=1 AND P2.s=1 AND P.code = P2.code)
ORDER BY P.id;
+----+--------+------+------+
| id | rownum | s | N |
+----+--------+------+------+
| 1 | 1 | 1 | 0 |
| 2 | 2 | 1 | 0 |
| 3 | 3 | 1 | 0 |
| 4 | 4 | 1 | 0 |
| 5 | 5 | NULL | 1 |
| 6 | 6 | 1 | 1 |
| 7 | 7 | 1 | 1 |
| 8 | 8 | 1 | 1 |
| 9 | 9 | 1 | 1 |
| 10 | 10 | NULL | 2 |
+----+--------+------+------+
Query 2: join on rownum column
SELECT P.id, P.rownum, P2.s,
IF(P2.s IS NULL, #val:=#val+1, #val) as N
FROM P CROSS JOIN (SELECT #val:=0) init
LEFT JOIN P P2
ON (P.rownum+1=P2.rownum AND P.s=1 AND P2.s=1 AND P.code = P2.code)
ORDER BY P.id;
+----+--------+------+------+
| id | rownum | s | N |
+----+--------+------+------+
| 1 | 1 | 1 | 0 |
| 2 | 2 | 1 | 0 |
| 3 | 3 | 1 | 0 |
| 4 | 4 | 1 | 0 |
| 5 | 5 | NULL | 1 |
| 6 | 6 | 1 | 0 |
| 7 | 7 | 1 | 0 |
| 8 | 8 | 1 | 0 |
| 9 | 9 | 1 | 0 |
| 10 | 10 | NULL | 2 |
+----+--------+------+------+
As explicitly documented both in MariaDB knowledge base and MySQL manual, you should not read a user-defined variable and set its value in the same statement, unless this statement is SET. For other statements it is unsafe and the result is not guaranteed, as your example clearly demonstrates.
Additional note: variables you are talking about in your question are more commonly referred to as 'user-defined variables' or 'user variables', as opposed to 'system variables', 'global variables' and 'session variables', each of which imply system-defined variables, either all of them or limited to the given scope.
I have a simple MySQL table as such:
| CUST_ID | VISIT | PROD_ID |
|---------|-------|---------|
| 1 | 1 | 3473 |
| 1 | 2 | 324 |
| 1 | 2 | 324 |
| 2 | 1 | 426 |
| 2 | 2 | 4418 |
| 3 | 1 | 4523 |
| 4 | 1 | 976 |
| 4 | 1 | 86 |
| 4 | 2 | 3140 |
| 4 | 3 | 1013 |
And I would like to transform it to this:
| CUST_ID | VISIT | PROD_IDs |
|---------|-------|----------|
| 1 | 1 | 3473 |
| 1 | 2 | 324, 324 |
| 2 | 1 | 426 |
| 2 | 2 | 4418 |
| 3 | 1 | 4523 |
| 4 | 1 | 976, 86 |
| 4 | 2 | 3140 |
| 4 | 3 | 1013 |
This is kinda an ugly hack, I get it.
I have no idea how to cleanly create such a thing. I've tried a variety of unsuccessful grouping strategies. Even a clue or hint in the right direction would be great. Thanks.
If you're trying to group by cust_id + visit, then you can do that and use a GROUP CONCAT on the PROD_ID field, for example:
SELECT
CUST_ID,
VISIT,
GROUP_CONCAT(PROD_ID) PROD_IDS
FROM
table
GROUP BY
CUST_ID,
VISIT
Reference: GROUP CONCAT
i want to find solution for my query problem. I need to find the SUM of all priceProduct*quantity and separated with each of productcategory. I have already made a query, but it takes longer time to executed it. this is my query,
SELECT
pb.ProductCategoryID,
pb.ProductCategoryDescription,
(SELECT
SUM((SELECT pd.HPP FROM `price details` pd WHERE pd.ProductID = pdt.ProductID ORDER BY pd.PriceDetailID DESC LIMIT 1)*
(SELECT StockProductBallance FROM `stock product` sp WHERE sp.ProductID = pdt.ProductID ORDER BY sp.StockProductID DESC LIMIT 1))
FROM product pdt
WHERE pdt.ProductCategoryID = pb.ProductCategoryID
) AS Total
FROM `product category` pb
GROUP BY pb.ProductCategoryID
this my example table
table product:
+------+-------+
| id_p | id_pc |
+------+-------+
| 1 | 3 |
| 2 | 4 |
| 3 | 3 |
| 4 | 4 |
+------+-------+
table productcategory:
+-------+---------+
| id_pc | pc_name |
+-------+---------+
| 3 | new_pc |
| 4 | old_pc |
+-------+---------+
table price details:
+---------------+------+-----+
| PriceDetailID | id_p | hpp |
+---------------+------+-----+
| 1 | 1 | 100 |
| 2 | 1 | 110 |
| 3 | 1 | 120 |
| 4 | 2 | 200 |
| 5 | 2 | 210 |
| 6 | 2 | 220 |
+---------------+------+-----+
table stockProduct:
+-----------------+------+---------------+
| id_stockProduct | id_p | stockballance |
+-----------------+------+---------------+
| 1 | 1 | 10 |
| 2 | 1 | 11 |
| 3 | 1 | 12 |
| 4 | 2 | 20 |
| 5 | 2 | 21 |
| 6 | 2 | 22 |
+-----------------+------+---------------+
Really need your help guys, for better query..
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
i want select tree from
id | parent_id | path | order
---------------------------------------
1 | 0 | /1/ | 1
2 | 1 | /1/2/ | 1
3 | 2 | /1/2/3/ | 1
4 | 1 | /1/4/ | 2
5 | 4 | /1/4/5/ | 2
6 | 4 | /1/4/6/ | 1
like this
| 1 | | |
| | 2 | |
| | | 3 |
| | 4 | |
| | | 6 |
| | | 5 |
in one query.
Something like
select * from tbl ORDER BY COALESCE(length(path),0), order asc
but this select sorted groups of each tree level
1
-2
-4
--3
--6
--5
thanks