Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL - Create View That Gets the Min/Max values of a collection of results

Tags:

sql

mysql

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:

  1. Gets all objects with parent = 0.
  2. For each of those objects, get all the child objects (WHERE parent = parent.id)
  3. The parent and its children consist of one objectGroup. The item in the new view consists of
    1. id = an autogenerated id. Probably optional but feels good to have.
    2. foreign_key = the same foreign key value as all objects in the objectGroup should have.
    3. start_date - min() of all start dates in the objectGroup.
    4. end_date - max() of all end dates in the objectGroup.
    5. number_of_objects - count() of all objects in the objectGroup
like image 454
Josh Dredge Avatar asked Dec 03 '21 05:12

Josh Dredge


People also ask

How do you find the difference between minimum and maximum values in SQL?

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`);

What is MIN () in MySQL?

MySQL MIN() Function The MIN() function returns the minimum value in a set of values.


1 Answers

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).

like image 99
Salman A Avatar answered Sep 29 '22 06:09

Salman A