Sum of Time differences while having times in 6 different columns - sql

I have following database
Station|Status | Start_hour | Start_minute | Start_second | End_hour | End_minute | End_second
Is it possible to sum up times for every entry that has end_ fields filled between given time?
Example:
Station|Status|Start_hour|Start_minute|Start_second|End_hour|End_minute|End_second
8 | 0 | 10 | 5 | 0 | NULL | NULL | NULL
8 | 1 | 10 | 5 | 0 | 10 | 15 | 30
2 | 1 | 9 | 53 | 0 | 10 | 16 | 45
7 | 0 | 10 | 23 | 0 | NULL | NULL | NULL
So the output would look like this:
Sum of time
29:15 */sum of times for stations 8 and 2(5:30 + 23:45)/*
Problem? I have to do it in single query

Related

Cumulative days across rows with several constraints SQL

I'm trying to figure out how to return a single line per Asset which shows the total days of cumulative Periods. However, I only want to add certain Periods depending on whether the StartDate is within 10 days of the EndDate of the previous Period.
TotalDays column in the sample data: If a Period does not have an EndDate the total days is Today (13/10/2018) minus the StartDate.
Breakdown of the Expected Output Table:
Row 1 / Asset1: TotalDays is 278 because
Period 2 started 1 day after Period 1 ended
and Period 3 started 6 days after Period 2 ended
therefore 63+29+186 = 278
Row 2 / Asset 2: TotalDays is 120 because
Period 1 and 2 are both Open so use the earliest StartDate
Today minus 15/06/2018 = 120
Row 3 / Asset 3: TotalDays is 66 because
Period 2 started over 10 days after Period 1 ended
If an Asset has no Open Periods it would not be displayed in the Output.
Happy to clarify anything as I know this is a bit fiddly!
Many Thanks.
Data Sample:
+-----+---------+--------+------------+------------+-----------+--------------------------------------+--------+
| Row | AssetID | Period | StartDate | EndDate | TotalDays | DaysBetweenEndDateAndStartDateOfNext | Status |
+-----+---------+--------+------------+------------+-----------+--------------------------------------+--------+
| 1 | 1 | 1 | 01/01/2018 | 05/03/2018 | 63 | NULL | Closed |
| 2 | 1 | 2 | 06/03/2018 | 04/04/2018 | 29 | 1 | Closed |
| 3 | 1 | 3 | 10/04/2018 | NULL | 186 | 6 | Open |
| 4 | 2 | 1 | 15/06/2018 | NULL | 120 | NULL | Open |
| 5 | 2 | 2 | 01/07/2018 | NULL | 104 | NULL | Open |
| 6 | 3 | 1 | 01/02/2018 | 10/02/2018 | 9 | NULL | Closed |
| 7 | 3 | 2 | 08/08/2018 | NULL | 66 | 179 | Open |
+-----+---------+--------+------------+------------+-----------+--------------------------------------+--------+
Expected Output:
+-----+---------+------------+---------+-----------+
| Row | AssetID | StartDate | EndDate | TotalDays |
+-----+---------+------------+---------+-----------+
| 1 | 1 | 01/01/2018 | NULL | 278 |
| 2 | 2 | 15/06/2018 | NULL | 120 |
| 3 | 3 | 08/08/2018 | NULL | 66 |
+-----+---------+------------+---------+-----------+

Deleting recursively in a function (ERROR: query has no destination for result data)

I have this table of relationships (only id_padre and id_hijo are interesting):
id | id_padre | id_hijo | cantidad | posicion
----+----------+---------+----------+----------
0 | | 1 | 1 | 0
1 | 1 | 2 | 1 | 0
2 | 1 | 3 | 1 | 1
3 | 3 | 4 | 1 | 0
4 | 4 | 5 | 0.5 | 0
5 | 4 | 6 | 0.5 | 1
6 | 4 | 7 | 24 | 2
7 | 4 | 8 | 0.11 | 3
8 | 8 | 6 | 0.12 | 0
9 | 8 | 9 | 0.05 | 1
10 | 8 | 10 | 0.3 | 2
11 | 8 | 11 | 0.02 | 3
12 | 3 | 12 | 250 | 1
13 | 12 | 5 | 0.8 | 0
14 | 12 | 6 | 0.8 | 1
15 | 12 | 13 | 26 | 2
16 | 12 | 8 | 0.15 | 3
This table store the links between nodes (id_padre = parent node and id_hijo = child node).
I'm trying to do a function for a recursive delete of rows where I begin with a particular row. After deleted, I check if there are more rows with id_hijo column with the same value I used to delete the first row.
If there aren't rows with this condition, I'll must to delete all the rows where id_padre are equal id_hijo of the deleted row.
i.e.: If I begin to delete the row where id_padre=3 and id_hijo=4 then I delete this row:
id | id_padre | id_hijo | cantidad | posicion
----+----------+---------+----------+----------
3 | 3 | 4 | 1 | 0
and the table remains like that:
id | id_padre | id_hijo | cantidad | posicion
----+----------+---------+----------+----------
0 | | 1 | 1 | 0
1 | 1 | 2 | 1 | 0
2 | 1 | 3 | 1 | 1
4 | 4 | 5 | 0.5 | 0
5 | 4 | 6 | 0.5 | 1
6 | 4 | 7 | 24 | 2
7 | 4 | 8 | 0.11 | 3
8 | 8 | 6 | 0.12 | 0
9 | 8 | 9 | 0.05 | 1
10 | 8 | 10 | 0.3 | 2
11 | 8 | 11 | 0.02 | 3
12 | 3 | 12 | 250 | 1
13 | 12 | 5 | 0.8 | 0
14 | 12 | 6 | 0.8 | 1
15 | 12 | 13 | 26 | 2
16 | 12 | 8 | 0.15 | 3
Because of there aren't any row with id_hijo = 4 I will delete the rows where id_padre = 4....and so on..recursively. (in this example the process end here)
I have try to do this function (this function calls itself):
CREATE OR REPLACE FUNCTION borrar(integer,integer) RETURNS VOID AS
$BODY$
DECLARE
padre ALIAS FOR $1;
hijo ALIAS FOR $2;
r copia_rel%rowtype;
BEGIN
DELETE FROM copia_rel WHERE id_padre = padre AND id_hijo = hijo;
IF NOT EXISTS (SELECT id_hijo FROM copia_rel WHERE id_hijo = hijo) THEN
FOR r IN SELECT * FROM copia_rel WHERE id_padre = hijo LOOP
RAISE NOTICE 'Selecciono: %,%',r.id_padre,r.id_hijo;--for debugging
SELECT borrar(r.id_padre,r.id_hijo);
END LOOP;
END IF;
END;
$BODY$
LANGUAGE plpgsql;
But I get this error:
ERROR: query has no destination for result data
I know that there are specific recursive ways in postgresql wit CTE. I have used it for traverse my graph, but I don't know how could use it in this case.
The error is due to the SELECT used to call the function recursively. PostgreSQL wants to put the results somewhere but is not told where.
If you want to run a function and discard results use PERFORM instead of SELECT in PL/PgSQL functions.

SQL how to force to display row with 0 if no data available?

My table returns results as following (skips row if HourOfDay does not have data for particular ID)
ID HourOfDay Counts
--------------------------
1 5 5
1 13 10
1 23 3
..........................HourOfDay up till 23
2 9 1
and so on.
What I am trying to achieve is to force showing rows displaying 0 for HoursOfDay, which don't have data, like following:
ID HourOfDay Counts
--------------------------
1 0 0
1 1 0
1 2 0
1......................
1 5 5
1 6 0
1......................
1 23 3
2 0 0
2 1 0
etc.
I have researched around about it. It looks like I can achieve this result if I create an extra table and outer join it. So I have created table variable in SP (as a temp workaround)
DECLARE #Hours TABLE
(
[Hour] INT NULL
);
INSERT INTO #Hours VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
,(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23);
However, no matter how I join it, it does not achieve desired result.
How do I proceed? Do I add extra columns to join on? Completely different approach? Any hint in the right direction is appreciated!
Using a derived table for the distinct Ids cross joined to #Hours, left joined to your table:
select
i.Id
, h.Hour
, coalesce(t.Counts,0) as Counts
from (select distinct Id from t) as i
cross join #Hours as h
left join t
on i.Id = t.Id
and h.Hour = t.HourOfDay
rextester demo: http://rextester.com/XFZYX88502
returns:
+----+------+--------+
| Id | Hour | Counts |
+----+------+--------+
| 1 | 0 | 0 |
| 1 | 1 | 0 |
| 1 | 2 | 0 |
| 1 | 3 | 0 |
| 1 | 4 | 0 |
| 1 | 5 | 5 |
| 1 | 6 | 0 |
| 1 | 7 | 0 |
| 1 | 8 | 0 |
| 1 | 9 | 0 |
| 1 | 10 | 0 |
| 1 | 11 | 0 |
| 1 | 12 | 0 |
| 1 | 13 | 10 |
| 1 | 14 | 0 |
| 1 | 15 | 0 |
| 1 | 16 | 0 |
| 1 | 17 | 0 |
| 1 | 18 | 0 |
| 1 | 19 | 0 |
| 1 | 20 | 0 |
| 1 | 21 | 0 |
| 1 | 22 | 0 |
| 1 | 23 | 3 |
| 2 | 0 | 0 |
| 2 | 1 | 0 |
| 2 | 2 | 0 |
| 2 | 3 | 0 |
| 2 | 4 | 0 |
| 2 | 5 | 0 |
| 2 | 6 | 0 |
| 2 | 7 | 0 |
| 2 | 8 | 0 |
| 2 | 9 | 1 |
| 2 | 10 | 0 |
| 2 | 11 | 0 |
| 2 | 12 | 0 |
| 2 | 13 | 0 |
| 2 | 14 | 0 |
| 2 | 15 | 0 |
| 2 | 16 | 0 |
| 2 | 17 | 0 |
| 2 | 18 | 0 |
| 2 | 19 | 0 |
| 2 | 20 | 0 |
| 2 | 21 | 0 |
| 2 | 22 | 0 |
| 2 | 23 | 0 |
+----+------+--------+

Return Rows as per Quantity of Columns Value In SQL

I have data in a table like below.
Now I want to return rows as per the values of the Quantity column.
Like above data row 1 have the Quantity 4 then in output of select query there will be 4 rows for row 1, similar to for row 2 quantity is 8 then there will be 8 rows.
When I have write query on above data then it should return 26 rows.
Query:
SQLFIDDLEExample
SELECT tbl.*
FROM tbl,
(SELECT number
FROM master..spt_values
WHERE Type = 'P') n
WHERE tbl.Quantity > n.number
Result:
| ROWNO | QUANTITY | SIZE |
|-------|----------|------|
| 1 | 4 | YXS |
| 1 | 4 | YXS |
| 1 | 4 | YXS |
| 1 | 4 | YXS |
| 2 | 8 | 2XL |
| 2 | 8 | 2XL |
| 2 | 8 | 2XL |
| 2 | 8 | 2XL |
| 2 | 8 | 2XL |
| 2 | 8 | 2XL |
| 2 | 8 | 2XL |
| 2 | 8 | 2XL |
| 3 | 7 | XL |
| 3 | 7 | XL |
| 3 | 7 | XL |
| 3 | 7 | XL |
| 3 | 7 | XL |
| 3 | 7 | XL |
| 3 | 7 | XL |
| 4 | 7 | YXS |
| 4 | 7 | YXS |
| 4 | 7 | YXS |
| 4 | 7 | YXS |
| 4 | 7 | YXS |
| 4 | 7 | YXS |
| 4 | 7 | YXS |
Explanation:
Column number from table spt_values contains continuous values from 0 to 2047 for Type 'P'.
These values are joined in, leading to 2048 duplicates returned for each record, and then restricted to return only the number of Quantity via the WHEREclause.

SQL Joining 2 Tables

I would like to merge two tables into one and also add a counter next to that. What i have now is
SELECT [CUCY_DATA].*, [DIM].[Col1], [DIM].[Col2],
(SELECT COUNT([Cut Counter]) FROM [MSD]
WHERE [CUCY_DATA].[Cut Counter] = [MSD].[Cut Counter]
) AS [Nr Of Errors]
FROM [CUCY_DATA] FULL JOIN [DIM]
ON [CUCY_DATA].[Cut Counter] = [DIM].[Cut Counter]
This way the data is inserted but where the values don't match nulls are inserted. I want for instance this
Table CUCY_DATA
|_Cut Counter_|_Data1_|_Data2_|
| 1 | 12 | 24 |
| 2 | 13 | 26 |
| 3 | 10 | 20 |
| 4 | 11 | 22 |
Table DIM
|_Cut Counter_|_Col1_|_Col2_|
| 1 | 25 | 40 |
| 3 | 50 | 45 |
And they need to be merged into:
|_Cut Counter_|_Data1_|_Data2_|_Col1_|_Col2_|
| 1 | 12 | 24 | 25 | 40 |
| 2 | 13 | 26 | 25 | 40 |
| 3 | 10 | 20 | 50 | 45 |
| 4 | 11 | 22 | 50 | 45 |
SO THIS IS WRONG:
|_Cut Counter_|_Data1_|_Data2_|_Col1__|_Col2__|
| 1 | 12 | 24 | 25 | 40 |
| 2 | 13 | 26 | NULL | NULL |
| 3 | 10 | 20 | 50 | 45 |
| 4 | 11 | 22 | NULL | NULL |
Kind regards, Bob
How are you getting the col1 and col2 values where there is no corresponding row in your DIM table? (Rows 2 and 4). Your "wrong" result is exactly correct, that's what the outer join does.