"SQL: copying data up"

Post #303027087 by figaro on Saturday 8th of December 2018 03:51:11 PM

Full Discussion: SQL: copying data up
Old 12-08-2018
SQL: copying data up

I need to fix an SQL statement in MySQL that should calculate a field using values from two of the columns and I prefer to do this using set-based programming, ie not procedural. What needs to happen is that in a separate column called "delta" the value of "level" is copied depending on whether "in_event" is 0 or 1. If it is 1, then the value of level is copied, else the last known value of delta is copied.
This is similar to how data is copied down in spreadsheets for underlying cells that have no value, except that in this case data is copied up instead of down.

These are the statements I am using:
Code:
create table `events` (
  `date` date default null,
  `sortorder` int(11) not null default '0',
  `level` float default null,
  `in_event` int(1) not null default '0'
);

insert into events values 
('2018-09-04', 2, 1547.8, 0),
('2018-09-03', 3, 1571, 1),
('2018-08-31', 4, 1541.6, 0),
('2018-08-30', 5, 1575.4, 0),
('2018-08-29', 6, 1596.6, 0),
('2018-08-28', 7, 1626.4, 0),
('2018-08-24', 8, 1575, 0),
('2018-08-23', 9, 1536, 0),
('2018-08-22', 10, 1579, 0),
('2018-08-21', 11, 1559, 1),
('2018-08-20', 12, 1554, 0),
('2018-08-17', 13, 1534, 0),
('2018-08-16', 14, 1543, 0),
('2018-08-15', 15, 1542.2, 0),
('2018-08-14', 16, 1646.8, 0),
('2018-08-13', 17, 1680.4, 0),
('2018-08-10', 18, 1667.6, 0),
('2018-08-09', 19, 1711.6, 0),
('2018-08-08', 20, 1726.6, 0),
('2018-08-07', 21, 1736.2, 1),
('2018-08-06', 22, 1678, 0),
('2018-08-03', 23, 1692.8, 0),
('2018-08-02', 24, 1655.4, 0),
('2018-08-01', 25, 1717.4, 0),
('2018-07-31', 26, 1732.8, 0),
('2018-07-30', 27, 1678, 0),
('2018-07-27', 28, 1691.4, 0),
('2018-07-26', 29, 1687.4, 0),
('2018-07-25', 30, 1700, 0),
('2018-07-24', 31, 1695, 0),
('2018-07-23', 32, 1604.6, 1),
('2018-07-20', 33, 1599.8, 0),
('2018-07-19', 34, 1622, 0),
('2018-07-18', 35, 1691, 0),
('2018-07-17', 36, 1666.2, 1);

I have gotten as far as the following, but it copies the data down instead of up:
Code:
alter table events add column delta decimal(10, 2);
update events set delta = level where in_event = 1;
select date, sortorder, level, in_event, case when delta is not NULL && @d := delta then delta else @d end as delta
from events
order by date desc;

This is the result that I am looking for:
Code:
insert into events values 
('2018-09-04', 2, 1547.8, 0, 1571),  -- value of 1571 is copied up, because it is the last known value and in_event is not 1
('2018-09-03', 3, 1571, 1, 1571),    -- value of 1571 is attained, because in_event is 1.
('2018-08-31', 4, 1541.6, 0, 1559),
('2018-08-30', 5, 1575.4, 0, 1559),
('2018-08-29', 6, 1596.6, 0, 1559),
('2018-08-28', 7, 1626.4, 0, 1559),
('2018-08-24', 8, 1575, 0, 1559),
('2018-08-23', 9, 1536, 0, 1559),
('2018-08-22', 10, 1579, 0, 1559),
('2018-08-21', 11, 1559, 1, 1736.2),
('2018-08-20', 12, 1554, 0, 1736.2),
('2018-08-17', 13, 1534, 0, 1736.2),
('2018-08-16', 14, 1543, 0, 1736.2),
('2018-08-15', 15, 1542.2, 0, 1736.2),
('2018-08-14', 16, 1646.8, 0, 1736.2),
('2018-08-13', 17, 1680.4, 0, 1736.2),
('2018-08-10', 18, 1667.6, 0, 1736.2),
('2018-08-09', 19, 1711.6, 0, 1736.2),
('2018-08-08', 20, 1726.6, 0, 1736.2),
('2018-08-07', 21, 1736.2, 1, 1736.2),
('2018-08-06', 22, 1678, 0, 1604.6),
('2018-08-03', 23, 1692.8, 0, 1604.6),
('2018-08-02', 24, 1655.4, 0, 1604.6),
('2018-08-01', 25, 1717.4, 0, 1604.6),
('2018-07-31', 26, 1732.8, 0, 1666.2),
('2018-07-30', 27, 1678, 0, 1666.2),
('2018-07-27', 28, 1691.4, 0, 1666.2),
('2018-07-26', 29, 1687.4, 0, 1666.2),
('2018-07-25', 30, 1700, 0, 1666.2),
('2018-07-24', 31, 1695, 0, 1666.2),
('2018-07-23', 32, 1604.6, 1, 1666.2),
('2018-07-20', 33, 1599.8, 0, 1666.2),
('2018-07-19', 34, 1622, 0, 1666.2),
('2018-07-18', 35, 1691, 0, 1666.2),
('2018-07-17', 36, 1666.2, 1, 1666.2);