Question

I have a bit of a tough one beating me here. We have a production warehouse where various products are created, we send out a daily production report using the following query but i would like to have this sorted hourly:

(Im trimming down the query to only a few products as its quite a biggie:

SET

@DayStart = '2013-10-24 07:00:00',
@DayEnd = '2013-10-24 16:00:00';

SELECT 
(SELECT COUNT(*) FROM t_container
    WHERE created_timestamp BETWEEN @DayStart AND @DayEnd
    AND container_type_id = '3'

) AS Product1,

(SELECT CONCAT (
    (SELECT COUNT(*) FROM t_container
    WHERE created_timestamp BETWEEN @DayStart AND @DayEnd
    AND container_type_id = '10'
    AND status_id = '4'
    ) , ' / ' ,
    (SELECT COUNT(*) FROM t_container
    WHERE created_timestamp BETWEEN @DayStart AND @DayEnd
    AND container_type_id = '10'
    AND status_id = '6'
    ))
) AS 'Product 1 EOL',

(SELECT COUNT(*) FROM t_container
    WHERE created_timestamp BETWEEN @DayStart AND @DayEnd
    AND container_type_id = '2'
    ) AS 'Product 2',

(SELECT COUNT(*) FROM t_container
    WHERE created_timestamp BETWEEN @DayStart AND @DayEnd
    AND container_type_id = '6'
    ) AS 'Product 3',

(SELECT CONCAT (
    (SELECT COUNT(*) FROM t_container
    WHERE created_timestamp BETWEEN @DayStart AND @DayEnd
    AND container_type_id = '9'
    AND status_id = '4'
    ) , ' / ' ,
    (SELECT COUNT(*) FROM t_container
    WHERE created_timestamp BETWEEN @DayStart AND @DayEnd
    AND container_type_id = '9'
    AND status_id = '6'
    ))
) AS 'Product 3 EOL',

(SELECT COUNT(*) FROM t_container
    WHERE created_timestamp BETWEEN @DayStart AND @DayEnd
    AND container_type_id = '4'
) AS 'Product 4',

(SELECT CONCAT (
    (SELECT COUNT(*) FROM t_container
    WHERE created_timestamp BETWEEN @DayStart AND @DayEnd
    AND container_type_id = '8'
    AND status_id = '4'
    ) , ' / ' ,
    (SELECT COUNT(*) FROM t_container
    WHERE created_timestamp BETWEEN @DayStart AND @DayEnd
    AND container_type_id = '8'
    AND status_id = '6'
    ))
) AS 'Product 4 EOL'

What i would like to achieve is to have the above report to run but the output be in 1 hour increments.

Any assistance would be greatly appreciated.

Please see below "expected output example"

TIME | Product 1 | Product 1 EOL | Product 2 | Product 3
07:00 | 12345 | 1 / 1 | 1568789 | 1 / 1
08:00 | 12345 | 1 / 1 | 1568789 | 1 / 1
09:00 | 12345 | 1 / 1 | 1568789 | 1 / 1

Was it helpful?

Solution

You have a row which contains a LOT of subselects

I would be tempted to recode these to subselect which are then joined into a single row (or just return multiple rows and do the formatted in you display code).

However to split one of those subselects up into hours you could use something like this (not tested):-

SELECT StartHour, COUNT(*) 
FROM 
(
    SELECT DATE_ADD(@DayStart, INTERVAL i HOUR) AS StartHour
    FROM
    (
        SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
    ) Sub1
) Sub2
LEFT OUTER JOIN t_container
ON created_timestamp BETWEEN Sub2.StartHour AND DATE_ADD(Sub2.StartHour, INTERVAL 3599 SECOND)
WHERE created_timestamp BETWEEN @DayStart AND @DayEnd
AND container_type_id = '3'
GROUP BY StartHour

This comes up with a range of hour time bands by adding to the start date, then uses that to do a left join against you data (adding 3599 seconds to get the end of the hour time bands), and doing a grouped count, doing GROUP BY on the starting hour.

EDIT

Not tested, but here is one way of doing it:-

SELECT StartHour, 
        EndHour, 
        COUNT(DISTINCT a.id) AS Product1,
        COUNT(DISTINCT b.id) AS 'Product 1 EOL 1',
        COUNT(DISTINCT c.id) AS 'Product 1 EOL 2',
        COUNT(DISTINCT d.id) AS 'Product 2',
        COUNT(DISTINCT e.id) AS 'Product 3',
        COUNT(DISTINCT f.id) AS 'Product 3 EOL 1',
        COUNT(DISTINCT g.id) AS 'Product 3 EOL 2',
        COUNT(DISTINCT h.id) AS 'Product 4',
        COUNT(DISTINCT i.id) AS 'Product 4 EOL 1',
        COUNT(DISTINCT j.id) AS 'Product 4 EOL 2'
FROM 
(
    SELECT DATE_ADD(@DayStart, INTERVAL i HOUR) AS StartHour, DATE_ADD(DATE_ADD(@DayStart, INTERVAL i HOUR), INTERVAL 3599 SECOND) AS EndHour
    FROM
    (
        SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
    ) Sub1
) Sub2
LEFT OUTER JOIN t_container a
ON a.created_timestamp BETWEEN Sub2.StartHour AND Sub2.EndHour
AND a.container_type_id = '3'
LEFT OUTER JOIN t_container b
ON b.created_timestamp BETWEEN Sub2.StartHour AND Sub2.EndHour
AND b.container_type_id = '10'
AND b.status_id = '4'
LEFT OUTER JOIN t_container c
ON c.created_timestamp BETWEEN Sub2.StartHour AND Sub2.EndHour
AND c.container_type_id = '10'
AND c.status_id = '6'
LEFT OUTER JOIN t_container d
ON d.created_timestamp BETWEEN Sub2.StartHour AND Sub2.EndHour
AND d.container_type_id = '2'
LEFT OUTER JOIN t_container e
ON e.created_timestamp BETWEEN Sub2.StartHour AND Sub2.EndHour
AND e.container_type_id = '6'
LEFT OUTER JOIN t_container f
ON f.created_timestamp BETWEEN Sub2.StartHour AND Sub2.EndHour
AND f.container_type_id = '9'
AND f.status_id = '4'
LEFT OUTER JOIN t_container g
ON g.created_timestamp BETWEEN Sub2.StartHour AND Sub2.EndHour
AND g.container_type_id = '9'
AND g.status_id = '6'
LEFT OUTER JOIN t_container h
ON h.created_timestamp BETWEEN Sub2.StartHour AND Sub2.EndHour
AND h.container_type_id = '4'
LEFT OUTER JOIN t_container i
ON i.created_timestamp BETWEEN Sub2.StartHour AND Sub2.EndHour
AND i.container_type_id = '8'
AND i.status_id = '4'
LEFT OUTER JOIN t_container j
ON j.created_timestamp BETWEEN Sub2.StartHour AND Sub2.EndHour
AND j.container_type_id = '8'
AND j.status_id = '6'
GROUP BY StartHour, EndHour

This is doing 1 subselect to get all the hour time bands, then joining the tables back to get the counts. However using so many COUNT(DISTINCT )) type statements might not perform that well.

Probably be possible to do the joins to get the hour ranges in each of the subselects that are then joined back, which might be better.

Note that I have brought back 2 columns for the columns that previously had 2 values split by a /.

Possibly slightly better (but also possibly slightly worse):-

SELECT Product1.rec_cnt AS Product1,
        CONCAT(Product1EOL1.rec_cnt, ' / ', Product1EOL2.rec_cnt) AS 'Product 1 EOL',
        Product2.rec_cnt AS 'Product 2',
        Product3.rec_cnt AS 'Product 3',
        CONCAT(Product3EOL1.rec_cnt, ' / ', Product3EOL2.rec_cnt) AS 'Product 3 EOL',
        Product4.rec_cnt AS 'Product 4',
        CONCAT(Product4EOL1.rec_cnt, ' / ', Product4EOL2.rec_cnt) AS 'Product 4 EOL'
FROM
(
    SELECT StartHour, EndHour, COUNT(t_container.id)  AS rec_cnt
    FROM 
    (
        SELECT DATE_ADD(@DayStart, INTERVAL i HOUR) AS StartHour, DATE_ADD(DATE_ADD(@DayStart, INTERVAL i HOUR), INTERVAL 3599 SECOND) AS EndHour
        FROM
        (
            SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
        ) Sub1
    ) Sub2
    LEFT OUTER JOIN t_container
    ON created_timestamp BETWEEN StartHour AND EndHour
    AND container_type_id = '3'
    GROUP BY StartHour, EndHour
) AS Product1
INNER JOIN
(
    SELECT StartHour, EndHour, COUNT(t_container.id)  AS rec_cnt
    FROM 
    (
        SELECT DATE_ADD(@DayStart, INTERVAL i HOUR) AS StartHour, DATE_ADD(DATE_ADD(@DayStart, INTERVAL i HOUR), INTERVAL 3599 SECOND) AS EndHour
        FROM
        (
            SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
        ) Sub1
    ) Sub2
    LEFT OUTER JOIN t_container
    ON created_timestamp BETWEEN StartHour AND EndHour
    AND container_type_id = '10'
    AND status_id = '4'
    GROUP BY StartHour, EndHour
) AS Product1EOL1
ON Product1.StartHour = Product1EOL1.StartHour AND Product1.EndHour = Product1EOL1.EndHour
INNER JOIN
(
    SELECT StartHour, EndHour, COUNT(t_container.id)  AS rec_cnt
    FROM 
    (
        SELECT DATE_ADD(@DayStart, INTERVAL i HOUR) AS StartHour, DATE_ADD(DATE_ADD(@DayStart, INTERVAL i HOUR), INTERVAL 3599 SECOND) AS EndHour
        FROM
        (
            SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
        ) Sub1
    ) Sub2
    LEFT OUTER JOIN t_container
    ON created_timestamp BETWEEN StartHour AND EndHour
    AND container_type_id = '10'
    AND status_id = '6'
    GROUP BY StartHour, EndHour
) AS Product1EOL2
ON Product1.StartHour = Product1EOL2.StartHour AND Product1.EndHour = Product1EOL2.EndHour
INNER JOIN
(
    SELECT StartHour, EndHour, COUNT(t_container.id)  AS rec_cnt
    FROM 
    (
        SELECT DATE_ADD(@DayStart, INTERVAL i HOUR) AS StartHour, DATE_ADD(DATE_ADD(@DayStart, INTERVAL i HOUR), INTERVAL 3599 SECOND) AS EndHour
        FROM
        (
            SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
        ) Sub1
    ) Sub2
    LEFT OUTER JOIN t_container
    ON created_timestamp BETWEEN StartHour AND EndHour
    AND container_type_id = '2'
    GROUP BY StartHour, EndHour
) AS Product2
ON Product1.StartHour = Product2.StartHour AND Product1.EndHour = Product2.EndHour
INNER JOIN
(
    SELECT StartHour, EndHour, COUNT(t_container.id)  AS rec_cnt
    FROM 
    (
        SELECT DATE_ADD(@DayStart, INTERVAL i HOUR) AS StartHour, DATE_ADD(DATE_ADD(@DayStart, INTERVAL i HOUR), INTERVAL 3599 SECOND) AS EndHour
        FROM
        (
            SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
        ) Sub1
    ) Sub2
    LEFT OUTER JOIN t_container
    ON created_timestamp BETWEEN StartHour AND EndHour
    AND container_type_id = '6'
    GROUP BY StartHour, EndHour
) AS Product3
ON Product1.StartHour = Product3.StartHour AND Product1.EndHour = Product3.EndHour
INNER JOIN
(
    SELECT StartHour, EndHour, COUNT(t_container.id)  AS rec_cnt
    FROM 
    (
        SELECT DATE_ADD(@DayStart, INTERVAL i HOUR) AS StartHour, DATE_ADD(DATE_ADD(@DayStart, INTERVAL i HOUR), INTERVAL 3599 SECOND) AS EndHour
        FROM
        (
            SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
        ) Sub1
    ) Sub2
    LEFT OUTER JOIN t_container
    ON created_timestamp BETWEEN StartHour AND EndHour
    AND container_type_id = '9'
    AND status_id = '4'
    GROUP BY StartHour, EndHour
) AS Product3EOL1
ON Product1.StartHour = Product3EOL1.StartHour AND Product1.EndHour = Product3EOL1.EndHour
INNER JOIN
(
    SELECT StartHour, EndHour, COUNT(t_container.id)  AS rec_cnt
    FROM 
    (
        SELECT DATE_ADD(@DayStart, INTERVAL i HOUR) AS StartHour, DATE_ADD(DATE_ADD(@DayStart, INTERVAL i HOUR), INTERVAL 3599 SECOND) AS EndHour
        FROM
        (
            SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
        ) Sub1
    ) Sub2
    LEFT OUTER JOIN t_container
    ON created_timestamp BETWEEN StartHour AND EndHour
    AND container_type_id = '9'
    AND status_id = '6'
    GROUP BY StartHour, EndHour
) AS Product3EOL2
ON Product1.StartHour = Product3EOL2.StartHour AND Product1.EndHour = Product3EOL2.EndHour
INNER JOIN
(
    SELECT StartHour, EndHour, COUNT(t_container.id)  AS rec_cnt
    FROM 
    (
        SELECT DATE_ADD(@DayStart, INTERVAL i HOUR) AS StartHour, DATE_ADD(DATE_ADD(@DayStart, INTERVAL i HOUR), INTERVAL 3599 SECOND) AS EndHour
        FROM
        (
            SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
        ) Sub1
    ) Sub2
    LEFT OUTER JOIN t_container
    ON created_timestamp BETWEEN StartHour AND EndHour
    AND container_type_id = '4'
    GROUP BY StartHour, EndHour
) AS Product4
ON Product4.StartHour = Product3.StartHour AND Product4.EndHour = Product3.EndHour
INNER JOIN
(
    SELECT StartHour, EndHour, COUNT(t_container.id)  AS rec_cnt
    FROM 
    (
        SELECT DATE_ADD(@DayStart, INTERVAL i HOUR) AS StartHour, DATE_ADD(DATE_ADD(@DayStart, INTERVAL i HOUR), INTERVAL 3599 SECOND) AS EndHour
        FROM
        (
            SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
        ) Sub1
    ) Sub2
    LEFT OUTER JOIN t_container
    ON created_timestamp BETWEEN StartHour AND EndHour
    AND container_type_id = '8'
    AND status_id = '4'
    GROUP BY StartHour, EndHour
) AS Product4EOL1
ON Product1.StartHour = Product4EOL1.StartHour AND Product1.EndHour = Product4EOL1.EndHour
INNER JOIN
(
    SELECT StartHour, EndHour, COUNT(t_container.id) AS rec_cnt
    FROM 
    (
        SELECT DATE_ADD(@DayStart, INTERVAL i HOUR) AS StartHour, DATE_ADD(DATE_ADD(@DayStart, INTERVAL i HOUR), INTERVAL 3599 SECOND) AS EndHour
        FROM
        (
            SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
        ) Sub1
    ) Sub2
    LEFT OUTER JOIN t_container
    ON created_timestamp BETWEEN StartHour AND EndHour
    AND container_type_id = '8'
    AND status_id = '6'
    GROUP BY StartHour, EndHour
) AS Product4EOL2
ON Product1.StartHour = Product4EOL2.StartHour AND Product1.EndHour = Product4EOL2.EndHour
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top