mysql inflation value calculation - mysql

I have a mysql table like this:
| data | valore | inflation |
+------------+---------+-----------+
| 2022-06-01 | 296.311 | NULL |
| 2022-05-01 | 292.296 | NULL |
| 2022-04-01 | 289.109 | NULL |
| 2022-03-01 | 287.504 | NULL |
| 2022-02-01 | 283.716 | NULL |
| 2022-01-01 | 281.148 | NULL |
| 2021-12-01 | 278.802 | NULL |
| 2021-11-01 | 277.948 | NULL |
| 2021-10-01 | 276.589 | NULL |
| 2021-09-01 | 274.310 | NULL |
| 2021-08-01 | 273.567 | NULL |
| 2021-07-01 | 273.003 | NULL |
| 2021-06-01 | 271.696 | NULL |
I would need to insert (update) inflation value, calculated as current year value / past year value.
For examle the inflation for 2022-06-01 should be given by 296.311/271.696 * 100 - 100 (or as percentage anyway).
How can I do?
Thank You

Use a self join in the UPDATE statement:
UPDATE tablename t1
INNER JOIN tablename t2 ON t2.data = t1.data - INTERVAL 1 YEAR
SET t1.inflation = t1.valore / t2.valore * 100 - 100;
See the demo.

Ho usato mySQL 8.0:
CREATE TABLE inflation_tab
(data DATE, valore FLOAT, inflazione FLOAT);
INSERT INTO inflation_tab VALUES
('2022-06-01', 296.311, NULL),
('2022-05-01', 292.296, NULL),
('2022-04-01', 289.109, NULL),
('2022-03-01', 287.504, NULL),
('2022-02-01', 283.716, NULL),
('2022-01-01', 281.148, NULL),
('2021-12-01', 278.802, NULL),
('2021-11-01', 277.948, NULL),
('2021-10-01', 276.589, NULL),
('2021-09-01', 274.310, NULL),
('2021-08-01', 273.567, NULL),
('2021-07-01', 273.003, NULL),
('2021-06-01', 271.696, NULL);
SET #last_val=271.696;
WITH cte AS (
SELECT data, valore, ROUND(valore/#last_val*100 - 100, 3) AS inflazione
FROM inflation_tab IT
)
UPDATE inflation_tab IT INNER JOIN cte ON (IT.data=cte.data)
SET IT.inflazione=cte.inflazione

Related

Mysql SELECT query group by with sum and avg

If I have added "group by date" then sum or avg function is not working.
Here is a table
| date | calories |
|-------------------------|
| 2021-03-28 | 42.50 |
| 2021-03-30 | 500.00 |
| 2021-03-31 | 35.00 |
| 2021-04-01 | 200.00 |
| 2021-04-01 | 35.00 |
Here is create Query
SELECT CONCAT(round(IF(avg(up.calories), avg(up.calories), 0), 2), "kcal") as avg, CONCAT(round(IF(SUM(up.calories), SUM(up.calories), 0), 2), "kcal") as total_burned
FROM `tbl` as `up`
WHERE `date` BETWEEN "2021-03-28" AND "2021-04-03"
AND `calories` != '0'
GROUP BY `date`
Below is my query result
| avg | total_burned |
|-----------------------------|
| 42.50 | 42.50 |
| 500.00 | 500.00 |
| 35.00 | 35.00 |
| 235.00 | 235.00 |
But actually, I want to this type of result
| avg | total_burned |
|-----------------------------|
| 203.13 | 812.50 |
Roll your own
DROP TABLE IF EXISTS T;
create table t( date date, calories decimal(10,2));
insert into t values
( '2021-03-28' , 42.50 ),
( '2021-03-30' , 500.00 ),
( '2021-03-31' , 35.00 ),
( '2021-04-01' , 200.00 ),
( '2021-04-01' , 35.00 );
select sum(calories) sumcal,sum(calories) / count(distinct date) calcavg, avg(calories)
from t;
+--------+------------+---------------+
| sumcal | calcavg | avg(calories) |
+--------+------------+---------------+
| 812.50 | 203.125000 | 162.500000 |
+--------+------------+---------------+
1 row in set (0.002 sec)

Update column of database table with numeric value column of the same table in MySql

The MySQL version is
mysql>
SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 8.0.17 |
+-----------+
1 row in set
With LOAD DATA syntax inserting into table text_table a csv file compiled by an external company
This is the text_table
Image 1
After LOAD DATA I need update the column sID_Branch with number value contains of columns sBranch, in this mode
All the next rows before the next sBranch should also be updated with that same id
Image 2
It's not possible to know in advance how many branches or rows number the csv file are contains, but at this moment there is no alternative to populate the table text_table
Any suggestion please?
Thanks in advance for any help
My table below
DROP TABLE IF EXISTS `text_table`;
CREATE TABLE `text_table` (
`sBranch` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`sID_Branch` int(11) DEFAULT NULL,
`sID` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`sID`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of text_table
-- ----------------------------
INSERT INTO `text_table` VALUES ('Branch 1', '1', '1');
INSERT INTO `text_table` VALUES ('- London', '1', '2');
INSERT INTO `text_table` VALUES ('Pepsi', '1', '3');
INSERT INTO `text_table` VALUES ('Coca Cola', '1', '4');
INSERT INTO `text_table` VALUES ('Dr Pepper', '1', '5');
INSERT INTO `text_table` VALUES ('- Springfield', '1', '6');
INSERT INTO `text_table` VALUES ('Fanta', '1', '7');
INSERT INTO `text_table` VALUES ('Duff', '1', '8');
INSERT INTO `text_table` VALUES ('Branch 2', '2', '9');
INSERT INTO `text_table` VALUES ('- Manchester', '2', '10');
INSERT INTO `text_table` VALUES ('Heineken', '2', '11');
INSERT INTO `text_table` VALUES ('Dreher', '2', '12');
INSERT INTO `text_table` VALUES ('Ceres', '2', '13');
INSERT INTO `text_table` VALUES ('- Mexico DF', '2', '14');
INSERT INTO `text_table` VALUES ('Corona', '2', '15');
Edit #1
+---------------+------------+-----+
| sBranch | sID_Branch | sID |
+---------------+------------+-----+
| Branch 1 | NULL | 1 |
| - London | NULL | 2 |
| Pepsi | NULL | 3 |
| Coca Cola | NULL | 4 |
| Dr Pepper | NULL | 5 |
| - Springfield | NULL | 6 |
| Fanta | NULL | 7 |
| Duff | NULL | 8 |
| Branch 2 | NULL | 9 |
| - Manchester | NULL | 10 |
| Heineken | NULL | 11 |
| Dreher | NULL | 12 |
| Ceres | NULL | 13 |
| - Mexico DF | NULL | 14 |
| Corona | NULL | 15 |
+---------------+------------+-----+
15 rows in set
Update table
+---------------+------------+-----+
| sBranch | sID_Branch | sID |
+---------------+------------+-----+
| Branch 1 | 1 | 1 |
| - London | 1 | 2 |
| Pepsi | 1 | 3 |
| Coca Cola | 1 | 4 |
| Dr Pepper | 1 | 5 |
| - Springfield | 1 | 6 |
| Fanta | 1 | 7 |
| Duff | 1 | 8 |
| Branch 2 | 2 | 9 |
| - Manchester | 2 | 10 |
| Heineken | 2 | 11 |
| Dreher | 2 | 12 |
| Ceres | 2 | 13 |
| - Mexico DF | 2 | 14 |
| Corona | 2 | 15 |
+---------------+------------+-----+
15 rows in set
Try something like this:
SET #tempid := 0;
UPDATE `text_table` SET `sID_Branch` = CASE WHEN `sBranch` like 'Branch%' THEN (#tempid := #tempid + 1) ELSE #tempid END;
Please note that it assumes that Branches are increasing by 1 every time.
I'm adding this one here just as a source of knowledge in case you need, Flash Thunder's answer is way cleaner.
Assuming that the pattern is consistent (it doesn't matter the increment in my case)
update text_table t
inner join
(
select sBranch,
case when (sBranch REGEXP 'Branch \d*') = 1
then #curBranch := trim(replace(sBranch, 'Branch ', ''))
else #curBranch end branchId,
sID
from text_table,
(select #curBranch := null) a
) x on t.sID = x.sID
set t.sID_Branch = x.branchId;
See it working here: http://sqlfiddle.com/#!9/a28ac0/1
Use window function SUM() to number the branches:
UPDATE text_table t
INNER JOIN (
SELECT *, SUM(sBranch LIKE 'Branch %') OVER (ORDER BY sID) grp
FROM text_table
) s ON s.sID = t.sID
SET t.siD_Branch = s.grp
See the demo.
Results:
> sBranch | sID_Branch | sID
> :------------ | ---------: | --:
> Branch 1 | 1 | 1
> - London | 1 | 2
> Pepsi | 1 | 3
> Coca Cola | 1 | 4
> Dr Pepper | 1 | 5
> - Springfield | 1 | 6
> Fanta | 1 | 7
> Duff | 1 | 8
> Branch 2 | 2 | 9
> - Manchester | 2 | 10
> Heineken | 2 | 11
> Dreher | 2 | 12
> Ceres | 2 | 13
> - Mexico DF | 2 | 14
> Corona | 2 | 15

MYSQL Variables LIMIT and subquery

I have a question about this mysql query on mysql Ver 14.14 Distrib 5.5.35:
I have a table named mytable with 3 columns date,value and id_patient.
CREATE TABLE `mytable`
( `date` DATE NOT NULL
, `id_patient` INT(11) NOT NULL
, `value` INT(3) NULL DEFAULT NULL
);
INSERT INTO `mytable` (`date`, `id_patient`, `value`) VALUES
('2019-11-17', '87321', '6'),
('2019-11-18', '87321', '1'),
('2019-11-19', '87321', '2'),
('2019-11-20', '87321', NULL),
('2019-11-21', '87321', '5'),
('2019-11-22', '87321', '8'),
('2019-11-23', '87321', NULL),
('2019-11-24', '87321', '3'),
('2019-11-25', '87321', '4'),
('2019-11-26', '87321', '6'),
('2019-11-27', '87321', '1'),
('2019-11-28', '87321', '10');
For each row i need to know the sum of 4th previous values not null.
SELECT #date:=date, value,
( SELECT SUM(value)
FROM mytable
WHERE date<#date
AND id_patient=87321
AND value IS NOT NULL
ORDER BY date DESC LIMIT 0,4 ) somme
FROM mytable
WHERE id_patient=87321
It doesnt work. The result is the same with or without ORDER BY date DESC LIMIT 0,4 and every rows before the current rows are selected.
Somebody know why ?
There is an example of the expected result:
+-------------+--------------------+--------+
| #date:=date | value | somme |
+-------------+--------------------+--------+
| 2019-11-17 | 6 | NULL | SUM OF 0 previous values not null
| 2019-11-18 | 1 | 6 | SUM OF 1 previous values not null
| 2019-11-19 | 2 | 7 | SUM OF 2 previous values not null
| 2019-11-20 | NULL | 9 | SUM OF 3 previous values not null
| 2019-11-21 | 5 | 9 | SUM OF 4 previous values not null
| 2019-11-22 | 8 | 14 | SUM OF 4 previous values not null
| 2019-11-23 | NULL | 16 | SUM OF 4 previous values not null
| 2019-11-24 | 3 | 16 | SUM OF 4 previous values not null
| 2019-11-25 | 4 | 18 | SUM OF 4 previous values not null
| 2019-11-26 | 6 | 20 | SUM OF 4 previous values not null
| 2019-11-27 | 1 | 21 | SUM OF 4 previous values not null
| 2019-11-28 | 10 | 14 | SUM OF 4 previous values not null
+-------------+--------------------+--------+
Thanks for your help :)
With a self join and aggregation:
select m.date, m.id_patient, m.value,
sum(mm.value) somme
from mytable m left join mytable mm
on mm.id_patient = m.id_patient and mm.value is not null and mm.date < m.date
and (
select count(*) from mytable
where id_patient = m.id_patient and value is not null
and date >= mm.date and date < m.date
) <= 4
where m.id_patient = '87321'
group by m.date, m.id_patient, m.value
See the demo.
Results:
| date | id_patient | value | somme |
| ---------- | ---------- | ----- | ----- |
| 2019-11-17 | 87321 | 6 | |
| 2019-11-18 | 87321 | 1 | 6 |
| 2019-11-19 | 87321 | 2 | 7 |
| 2019-11-20 | 87321 | | 9 |
| 2019-11-21 | 87321 | 5 | 9 |
| 2019-11-22 | 87321 | 8 | 14 |
| 2019-11-23 | 87321 | | 16 |
| 2019-11-24 | 87321 | 3 | 16 |
| 2019-11-25 | 87321 | 4 | 18 |
| 2019-11-26 | 87321 | 6 | 20 |
| 2019-11-27 | 87321 | 1 | 21 |
| 2019-11-28 | 87321 | 10 | 14 |
The sum() already took place on all rows before you limit the results. Limit first the result before applying the sum() function using another subquery.
SELECT #date:=date, value,
(SELECT sum(value) from
(SELECT value
FROM mytable
WHERE date<#date
AND id_patient=87321
AND value IS NOT NULL
ORDER BY date DESC LIMIT 0,4))
FROM mytable
WHERE date<#date
AND id_patient=87321
AND value IS NOT NULL
ORDER BY date DESC LIMIT 0,4

Order result by IDs with the most recent date

I tried a lot, but I cannot figure out a way to do this:
I have a table with (not unique) IDs and dates. All entries should be selected in the end, but they need to be sorted.
Table:
+----+------------+
| id | date |
+----+------------+
| 1 | 2017-12-10 |
| 1 | 2015-05-22 |
| 7 | 2016-04-05 |
| 2 | 2017-12-12 |
| 2 | 2014-03-10 |
| 7 | 2016-01-14 |
| 1 | 2016-08-17 |
+----+------------+
What I need:
+----+------------+
| id | date |
+----+------------+
| 2 | 2017-12-12 |
| 2 | 2014-03-10 |
| 1 | 2017-12-10 |
| 1 | 2016-08-17 |
| 1 | 2015-05-22 |
| 7 | 2016-04-05 |
| 7 | 2016-01-14 |
+----+------------+
I need everything "grouped" by the ids, starting with the id that has the most recent date linked to it.
id: 2 / date: 2017-12-12
has the most recent date, so now all rows with Id 2 follow, ordered by the date descending. After that, which "block" of ids comes next is determined again by the next most recent date and so on.
Using a subquery that groups by id, we get the max date, then joining this to the source data gives us the max date on every row to sort by.
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE Table1
(`id` int, `date` datetime)
;
INSERT INTO Table1
(`id`, `date`)
VALUES
(1, '2017-12-10 00:00:00'),
(1, '2015-05-22 00:00:00'),
(7, '2016-04-05 00:00:00'),
(2, '2017-12-12 00:00:00'),
(2, '2014-03-10 00:00:00'),
(7, '2016-01-14 00:00:00'),
(1, '2016-08-17 00:00:00')
;
Query 1:
select t.*
from table1 t
inner join (
select id, max(`date`) maxdate
from table1
group by id
) g on t.id = g.id
order by g.maxdate DESC, t.id, t.date DESC
Results:
| id | date |
|----|----------------------|
| 2 | 2017-12-12T00:00:00Z |
| 2 | 2014-03-10T00:00:00Z |
| 1 | 2017-12-10T00:00:00Z |
| 1 | 2016-08-17T00:00:00Z |
| 1 | 2015-05-22T00:00:00Z |
| 7 | 2016-04-05T00:00:00Z |
| 7 | 2016-01-14T00:00:00Z |
if your table is stack
SELECT * FROM `stack` LEFT OUTER JOIN (SELECT * FROM `stack` GROUP BY `id` )t1 ON
`stack`.`id` = t1.`id` ORDER BY t1.`date` DESC,`stack`.`date` DESC

Include NULL in SQL Join when using WHERE

I have the following two tables:
Table TempUser22 : 57,000 rows:
+------+-----------+
| Id | Followers |
+------+-----------+
| 874 | 55542 |
| 1081 | 330624 |
| 1378 | 17919 |
| 1621 | 920 |
| 1688 | 255463 |
| 2953 | 751 |
| 3382 | 204466 |
| 3840 | 273489 |
| 4145 | 376 |
| ... | ... |
+------+-----------+
Table temporal_users : 10,000,000 rows total, 3200 rows Where Date=2010-12-31:
+---------------------+---------+--------------------+
| Date | User_Id | has_original_tweet |
+---------------------+---------+--------------------+
| 2008-02-22 12:00:00 | 676493 | 2 |
| 2008-02-22 12:00:00 | 815263 | 1 |
| 2008-02-22 12:00:00 | 6245822 | 1 |
| 2008-02-22 12:00:00 | 8854092 | 1 |
| 2008-02-23 12:00:00 | 676493 | 2 |
| 2008-02-23 12:00:00 | 815263 | 1 |
| 2008-02-23 12:00:00 | 6245822 | 1 |
| 2008-02-23 12:00:00 | 8854092 | 1 |
| 2008-02-24 12:00:00 | 676493 | 2 |
| ............. | ... | .. |
+---------------------+---------+--------------------+
I am running the following join query on these tables:
SELECT sum(has_original_tweet), b.Id
FROM temporal_users AS a
RIGHT JOIN TempUser22 AS b
ON a.User_ID = b.Id
GROUP BY b.Id;
Which returns 57,00 rows as expected, with NULL answers on the first field:
+-------------------------+------+
| sum(has_original_tweet) | Id |
+-------------------------+------+
| NULL | 874 |
| NULL | 1081 |
| 135 | 1378 |
| 164 | 1621 |
| 652 | 1688 |
| 691 | 2953 |
| NULL | 3382 |
| NULL | 3840 |
| NULL | 4145 |
| ... | .... |
+-------------------------+------+
However, when adding the WHERE line specifying a date as below:
SELECT sum(has_original_tweet), b.Id
FROM temporal_users AS a
RIGHT JOIN TempUser22 AS b
ON a.User_ID = b.Id
WHERE a.Date BETWEEN '2010-12-31-00:00:00' AND '2010-12-31-23:59:59'
GROUP BY b.Id;
I receive the following answer, of only 3200 rows, and without any NULL in the first field.
+-------------------------+---------+
| sum(has_original_tweet) | Id |
+-------------------------+---------+
| 1 | 797194 |
| 1 | 815263 |
| 0 | 820678 |
| 1 | 1427511 |
| 0 | 4653731 |
| 1 | 5933862 |
| 2 | 7530552 |
| 1 | 7674072 |
| 1 | 8149632 |
| .. | .... |
+-------------------------+---------+
My question is: How to get, for a given date, an answer of size 57,000 rows for each user in TempUser22 with NULL values when has_original_tweet is not present in temporal_user for the given date?
Thanks.
SELECT b.Id, SUM(a.has_original_tweet) s
FROM TempUser22 b
LEFT JOIN temporal_users a ON b.Id = a.User_Id
AND a.Date BETWEEN '2010-12-31-00:00:00' AND '2010-12-31-23:59:59'
GROUP BY b.Id;
Id s
1 null
2 1
3 null
4 3
5 null
6 null
For debugging, I used:
CREATE TEMPORARY TABLE TempUser22(Id INT, Followers INT)
SELECT 1 Id, 10 Followers UNION ALL
SELECT 2, 20 UNION ALL
SELECT 3, 30 UNION ALL
SELECT 4, 40 UNION ALL
SELECT 5, 50 UNION ALL
SELECT 6, 60
;
CREATE TEMPORARY TABLE temporal_users(`Date` DATETIME, User_Id INT, has_original_tweet INT)
SELECT '2008-02-22 12:00:00' `Date`, 1 User_Id, 1 has_original_tweet UNION ALL
SELECT '2008-12-31 12:00:00', 2, 1 UNION ALL
SELECT '2010-12-31 12:00:00', 2, 1 UNION ALL
SELECT '2012-12-31 12:00:00', 2, 1 UNION ALL
SELECT '2008-12-31 12:00:00', 4, 9 UNION ALL
SELECT '2010-12-31 12:00:00', 4, 1 UNION ALL
SELECT '2010-12-31 12:00:00', 4, 2 UNION ALL
SELECT '2012-12-31 12:00:00', 4, 9
;
That's because NULL values will always be discarded from the where clause
You can use a coalesce in your where clause.
WHERE coalesce(a.Date, 'some-date-in-the-range') BETWEEN '2010-12-31-00:00:00' AND '2010-12-31-23:59:59'
With this instead, you force null values to be considered as valid.