Delving into some complex SQL here. I want to create a view/virtual table.
I have an object table. Which looks something like this (all values are int)
| id | parent_id | foreign_key | start_date | end_date |
CREATE TABLE objects (
id int AUTO_INCREMENT PRIMARY KEY,
parent_id INT(11),
foreign_key INT(11),
start_date INT(11),
end_date INT(11)
);
INSERT INTO objects
VALUES
(1, 0, 1, 1638930577, 1638930578),
(2, 1, 1, 1638930578, 1638930578),
(3, 2, 1, 1638930578, 1638930578),
(4, 0, 2, 1638930576, 1638930578),
(5, 4, 2, 1638930578, 1638930578),
(6, 5, 2, 1638930578, 1638930578),
(7, 0, 1, 1638930574, 1638930578),
(8, 7, 1, 1638930578, 1638930578),
(9, 7, 1, 1638930578, 1638930579)
I want to create a view that looks like
| id | start_date | end_date | number_of_objects |
I've never used SQL views before, and would be ideal in my situation rather than writing code. Is this possible? My main qualm is that when I do this in code, I need to give it an object_id to start, really not sure how to just get a group of objects with the same parent id that isn't 0.
Thank you
P.S Using MySQL/Maria most recent version but dialect probably isn't super important.
SQL Fiddle: http://sqlfiddle.com/#!9/429570/1
The return result from the new view, provided from the schedule should look like
id | foreign_key | start_date | end_date | number_of_objects |
---|---|---|---|---|
1 | 1 | 1638930577 | 1638930578 | 3 |
2 | 2 | 1638930576 | 1638930578 | 3 |
3 | 1 | 1638930574 | 1638930579 | 3 |
The return result should be built something like this:
objectGroup
. The item in the new view consists of
SELECT date(`date`), (max(value) - min(value)) as value, FROM `sub_meter_data` where date(sub_meter_data. date) > '2012-10-01' and sub_meterID in('58984','58985','58986','58987') group by date(`date`);
MySQL MIN() Function The MIN() function returns the minimum value in a set of values.
Looks like your data is three levels deep (may be deeper). You can use recursion to traverse from parent to child to grandchildren. This requires MySQL 8 or later unfortunately:
with recursive rcte as (
/***
select all topmost level rows
the id and foreign_key of the parent will be "copied" to all children and grandchildren
the last id column is needed to link the next set of rows with this one
***/
select id as group_id, foreign_key, start_date, end_date, id
from objects
where parent_id = 0
union all
/***
p is the set of rows from previous iteration (this is how recursive cte works)
c is the set of rows that are direct children of p
p.group_id and p.foreign_key are copied from parent (which in turn were copied from their parent and so on)
***/
select p.group_id, p.foreign_key, c.start_date, c.end_date, c.id
from rcte as p
join objects as c on c.parent_id = p.id
)
/***
all "object groups" now have same group_id and foreign_key
we just need to group by
***/
select group_id, foreign_key, min(start_date) as start_date, max(end_date) as end_date, count(*) as number_of_objects
from rcte
group by group_id, foreign_key
db<>fiddle
You might want to consider other models for storing the data. Adjacency list (the one you're using) is simpler to maintain (insert, update, delete) but difficult to query (e.g find subtree of given node) without recursion. Nested set model is a good alternate which is simpler to query but difficult to maintain. Materialized paths model is another candidate which is simple to query but difficult to maintain (easier to implement with array datatype but no referential integrity).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With