how to derived value of a filed from another field in MySql - mysql

I have a table as below
+---+------------+----------+
| ID| Date | Amount_1 |
+---+------------+----------+
| 1 | 2016-02-02 | 100.00 |
| 1 | 2016-02-05 | 150.00 |
| 1 | 2016-02-09 | 125.00 |
| 1 | 2016-02-11 | 75.00 |
| 1 | 2016-02-19 | -46.99 |
| 1 | 2016-02-20 | -41.33 |
| 1 | 2016-02-29 | -14.15 |
+---+------------+----------+
I want to derived another column in this table say Amount_2 from Amount_1, and the value for each row of Amount_2 must be the sum of previous row and current row of Amount_1 column.
I mean I want to get the below table.
+---+------------+----------+----------+
| ID| Date | Amount_1 | Amount_2 |
+---+------------+----------+----------+
| 1 | 2016-02-02 | 100.00 | 100.00 |
| 1 | 2016-02-05 | 150.00 | 250.00 |
| 1 | 2016-02-09 | 125.00 | 375.00 |
| 1 | 2016-02-11 | 75.00 | 450.00 |
| 1 | 2016-02-19 | -46.99 | 403.01 |
| 1 | 2016-02-20 | -41.33 | 361.68 |
| 1 | 2016-02-29 | -14.15 | 347.53 |
+---+------------+----------+----------+

Try like this:
SELECT m.ID, m.Date, m.Amount_1, (#x:= m.Amount_1 + #x) AS Amount_2
FROM mytable m,(SELECT #x:=0) c

You can get by using session varable
SET #old_amount = 0;
SELECT ID, Date,Amount_1, (#old_amount := Amount_1 + #old_amount) AS Amount_2
FROM table_name
ORDER BY date;

Related

SQL : For each ID, only display the highest value from another column (can't group by)

I have this table here :
+---------+----------+------------+------------+
| idStep | idProj | dateStart | dateEnd |
+---------+----------+------------+------------+
| 1 | 1 | 2011-07-01 | 2011-09-01 |
| 1 | 2 | 2012-05-01 | 2012-05-10 |
| 1 | 3 | 2011-11-01 | 2012-01-20 |
| 2 | 1 | 2011-09-02 | 2011-11-30 |
| 2 | 2 | 2012-05-11 | 2012-06-01 |
| 2 | 3 | 2012-01-21 | 2012-04-01 |
| 3 | 1 | 2011-12-01 | 2012-07-07 |
| 3 | 2 | 2012-06-02 | 2012-07-01 |
| 3 | 3 | 2012-04-02 | NULL |
| 4 | 1 | 2012-07-08 | NULL |
| 4 | 2 | 2012-07-01 | 2012-07-21 |
| 5 | 2 | 2012-07-22 | 2012-07-23 |
+---------+----------+------------+------------+
I need to find the current step of each project by searching for the highest idStep of each idProject without using Group By, which is where I'm completely stuck. Without GROUP BY I just cannot get there.
Basically, the output should be this :
+---------+----------+------------+------------+
| idStep | idProj | dateStart | dateEnd |
+---------+----------+------------+------------+
| 3 | 3 | 2012-04-02 | NULL |
| 4 | 1 | 2012-07-08 | NULL |
| 5 | 2 | 2012-07-22 | 2012-07-23 |
+---------+----------+------------+------------+
I want to use a Query built like this
SELECT idProj,idStep
FROM table
WHERE idStep = (SELECT max(idStep) FOR EACH idProj)
I know that FOR EACH isn't SQL, I'm only trying to make my desired query structure readable.
You want a correlated subuqery:
SELECT idProj, idStep
FROM table t
WHERE t.idStep = (SELECT max(idStep)
FROM table t2
WHERE t2.idProj = t.idProj
);

mysql create multiple select to put max in all rows

This is my table with sample data:
Table:PersTrans
+------------+-------------+------+-----+------------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+------------+-------+
| PersTrID | char(10) | NO | PRI | | |
| PersTrSeq | int(11) | NO | PRI | 0 | |
| PersTrDate | date | YES | | 1001-01-01 | |
| PersTrPaid | float(9,2) | YES | | 0.00 | |
+------------+-------------+------+-----+------------+-------+
mysql> select * from PersTrans;
+------------+-----------+-----------+-------------+
| PersTrID | PersTrSeq | PersTrDate | PersTrPaid |
+------------+-----------+-----------+-------------+
| MOCK | 1 | 2015-10-10 | 400.00 |
| MOCK | 2 | 2017-11-07 | 10.00 |
| NAGA | 1 | 2015-11-11 | 500.00 |
| NASSA | 1 | 2015-12-16 | 800.00 |
+------------+-----------+-----------+-------------+
I'd like to pick up the maximum PersTrSeq, and attach it to all the records that have the same PersTrId. What I want:
+------------+-----------+------------+------------+----------------+
| PersTrID | PersTrSeq | PersTrDate | PersTrPaid | max(PersTrSeq) |
+------------+-----------+-----------+------------+-----------------+
| MOCK | 1 | 2015-10-10 | 400.00 | 2 |
| MOCK | 2 | 2017-11-07 | 10.00 | 2 |
| NAGA | 1 | 2015-11-11 | 500.00 | 1 |
| NASSA | 1 | 2015-12-16 | 800.00 | 1 |
+------------+-----------+-----------+------------+-----------------+
These two attempts didn't work. I've looked for other suggestions but haven't found anything helpful.
mysql> SELECT *, max(PersTrSeq) from PersTrans where PersTransId = 'Mock' group by PersTrSeq;
+------------+-----------+------------+------------+----------------+
| PersTrID | PersTrSeq | PersTrDate | PersTrPaid | max(PersTrSeq) |
+------------+-----------+-----------+------------+-----------------+
| MOCk | 1 | 2015-10-10 | 400.00 | 1 |
| MOCK | 2 | 2017-11-07 | 10.00 | 2 |
+------------+-----------+-----------+------------+-----------------+
mysql> SELECT *, max(PersTrSeq) as maxseq from PersTrans group by PersTrId;
+------------+-----------+------------+------------+--------+
| PersTrID | PersTrSeq | PersTrDate | PersTrPaid | maxseq |
+------------+------------+-----------+------------+--------+
| MOCK | 1 | 2015-10-10 | 400.00 | 2 |
| NAGA | 1 | 2015-11-11 | 500.00 | 1 |
| NASSA | 1 | 2015-12-16 | 800.00 | 1 |
+------------+-----------+-----------+------------+---------+
Can anyone offer a single query that will get the result I'm looking for?
Following query will work:
select *,
(select max(PersTrSeq) from PersTrans p2
where p2.PersTrId = p1.PersTrId
) as maxSeq
from PersTrans p1;
If I understand what you want, you want the same number of records as the actual data, substituting the max(PersTrSeq) for all rows with a certain PersTrID.
SELECT
`PerTrID`,
(SELECT max(`PersTrSeq`) FROM `PersTrans` b WHERE b.`PersTrID = a.`PersTrID`) as `PersTrSeq`,
`PersTrDate`,
`PersTrPaid`,
from `PersTrans` a

Creating a log having the date of purchase

I need to create a log having the purchase date of an item.
Items can be owned by only one buyer at time. So, for example, if item1 was purchased by buyer2 in 2009 and after by buyer1 in 2015, then between 2009 and 2015 was owned by buyer2.
Here is my table:
+--------+------------+-----------+----------+
| id_doc | date | id_item | id_buyer |
+--------+------------+-----------+----------+
| 11 | 2016-06-07 | 1 | 4 |
| 10 | 2016-06-06 | 1 | 4 |
| 1 | 2015-11-30 | 1 | 1 |
| 9 | 2009-01-01 | 1 | 2 |
| 4 | 2001-01-12 | 1 | 2 |
| 8 | 1996-06-06 | 1 | 2 |
| 3 | 1995-05-29 | 1 | 1 |
| 2 | 1998-05-23 | 2 | 2 |
| 7 | 2014-10-10 | 3 | 2 |
| 6 | 2003-12-12 | 3 | 3 |
| 5 | 1991-01-12 | 3 | 2 |
+--------+------------+-----------+----------+
Here is a kind of table/view I need:
+------------+------------+-----------+----------+--------+
| date_from | date_to | id_item | id_buyer | id_doc |
+------------+------------+-----------+----------+--------+
| 2016-06-07 | - | 1 | 4 | 11 |
| 2016-06-06 | 2016-06-07 | 1 | 4 | 10 |
| 2015-11-30 | 2016-06-06 | 1 | 1 | 1 |
| 2009-01-01 | 2015-11-30 | 1 | 2 | 9 |
| 2001-01-12 | 2009-01-01 | 1 | 2 | 4 |
| 1996-06-06 | 2001-01-12 | 1 | 2 | 8 |
| 1995-05-29 | 1996-06-06 | 1 | 1 | 3 |
| 1998-05-23 | - | 2 | 2 | 2 |
| 2014-10-10 | - | 3 | 2 | 7 |
| 2003-12-12 | 2014-10-10 | 3 | 3 | 6 |
| 1991-01-12 | 2003-12-12 | 3 | 2 | 5 |
+------------+------------+-----------+----------+--------+
I've tried a lot with GROUP BY, GROUP_CONCAT, trying to access next record date, etc ... but I can't found out how to solve the problem.
Thanks in advance.
I finally found out the solution only for past purchases.
SELECT
main.id_doc, main.id_item, main.date AS "date_from", bi.date AS "date_to", main.id_buyer
FROM
MyTable main, MyTable bi
WHERE
bi.id_doc =
(
SELECT sub.id_doc
FROM MyTable sub
WHERE sub.id_item = main.id_item AND sub.date > main.date ORDER BY sub.date ASC LIMIT 1
);

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