Time difference between two date fields - sql

I have a date field names "dts" in string format. I want to find out all the records based on their time differences (in hours). The run event time should be greater than or equal to eat event.
The output should be:

Convert timestamps to seconds, then subtract, divide result by 3600 to get hours, use case+count to count by ranges, something like this:
select count(case when diff_hrs >24 then 1 end) as more_24,
count(case when diff_hrs <=24 then 1 end) as less_than_24,
...
count(case when diff_hrs >=2 and diff_hrs <=3 then 1 end) as hrs_2_to_3,
...
from
(
select
abs(unix_timestamp(dts) - unix_timestamp(dts-eat)))/60/60 as diff_hrs
from table
)s;

Related

Flag 2 actual vs benchmark readings every rolling 12 hours in SQL Developer Query

Looking for some help with code in SQL Developer query to flag any 2 temperature readings - every rolling 12 hours - if they are greater than the acceptable benchmark of 101 deg F.
The given data fields are:
Temp Recorded (DT/TM data type ; down to seconds)
Reading Value (number data type)
Patient ID
There are multiple readings taken throughout a patients stay, at random times.
Logically, we can check if two adjacent times total 12 hrs or more & EACH of their temp readings are >101 but not sure how to put it into a CASE statement (unless there's a better SQL syntax).
Will really appreciate if a SQL only solution can be recommended.
Many Thanks
Giving the code below including the CASE statement as provided by #Gordon Linoff underneath. The below sample code is part of a bigger query joining multiple tables:
SELECT CE.PatientID, CE.ReadingValue, CE.TempRecorded_DT_TM,
(case when sum(case when readingvalue > 101 then 1 else 0 end) over (
partition by patientid
order by dt
range between '12' hour preceding and current row
) >= 2
then 'Y' else 'N'
end) as temp_flag
FROM
edw.se_clinical_event CE
WHERE
CE.PatientID = '176660214'
AND
CE.TempRecorded_DT_TM >= '01-JAN-20'
ORDER BY
TempRecorded_DT_TM
If you want two readings in 12 hours that are greater than 101, then you can use a rolling sum with a window frame:
select t.*,
(case when sum(case when readingvalue > 101 then 1 else 0 end) over (
partition by patientid
order by dt
range between interval '12' hour preceding and current row
) >= 2
then 'Y' else 'N'
end) as temp_flag
from t;

SQL Query : Is it possible to project a four results in a single query?

Currently, I am executing four queries to project the results based last 24hours, last week, last month and last month. Is it possible to project a four results in a single query?
If you need last one week, last one month, last one year compared to current date then you can do it using conditional aggregation in oracle as following:
Select sum(case when trunc(date_col) = trunc(sysdate-1) then 1 end) as last_one_day,
sum(case when trunc(date_col) between trunc(sysdate-7) and trunc(sysdate-1) then 1 end) as last_one_week,
sum(case when trunc(date_col) between trunc(add_months(sysdate,-1)) and trunc(sysdate-1) then 1 end) as last_one_month,
sum(case when trunc(date_col) between trunc(add_months(sysdate,-12)) and trunc(sysdate-1) then 1 end) as last_one_year
From your_table
Where type = ...
Cheers!!

SQL Report - query multiple tables

I have been working on a Stats page in APEX and currently have the following report query:
select to_char(DATELOGGED,'Month - YYYY') as Month,
COUNT(*) as "Total Calls",
SUM(case when CLOSED is null then 1 else null end) as "Open",
COUNT(case CLOSED when 'Y' then 1 else null end) as "Closed",
SUM(case when EXTREF is null then 0 else 1 end) as "Referred",
round((COUNT(case SLA_MET when 'Y' then 1 else null end)/COUNT(case CLOSED when 'Y' then 1 else null end)*100),2) as "SLA Met %"
from IT_SUPPORT_CALLS
GROUP BY to_char(DATELOGGED,'Month - YYYY')
order by MIN (DATELOGGED) desc
I wish to add the sum of DURATION from a different table:
select
"START_TIME",
DECODE(DURATION,null,'Open',((select extract( minute from DURATION )
+ extract( hour from DURATION ) * 60
+ extract( day from DURATION ) * 60 * 24
from dual)||' minutes')) DURATION
from "IT_DOWNTIME"
The IT_DOWNTIME table uses START_TIME (varchar2) as the date identifier, the IT_SUPPORT_CALLS uses DATELOGGED (DATE) as date identifier.
The current output for IT_DOWNTIME is for example:
08-FEB-2019 - 30 Minutes
20-FEB-2019 - 15 Minutes
I would like the report SUM and group IT_DOWNTIME and add this into the existing report.
Hope this makes sense.
Please let me know if I missed any information that would help to resolve this.
Many thanks
Thanks for that, much appreciated. Unfortunately it doesn't return any data from IT_DOWNTIME.
I'm guessing the different date formats doesn't help, hope this clears things up a bit:
These are the columns in IT_DOWNTIME that are of interest:
START_TIME ( VARCHAR2(30) )
DURATION ( INTERVAL DAY(2) TO SECOND(6) )
Example of current IT_DOWNTIME output without formatting:
START_TIME
06-JUL-2016 11:05
DURATION
+00 00:35:00.000000
Example of current IT_SUPPORT_CALLS output without formatting:
DATELOGGED
06/07/2016
Something like this will probably do it, but there has been some guesswork as to your column names etc:
SELECT *
FROM
(
SELECT
to_char(DATELOGGED,'MON-YYYY') as Month,
COUNT(*) as Total_Calls,
SUM(case when CLOSED is null then 1 else null end) as case_Open,
COUNT(case CLOSED when 'Y' then 1 else null end) as case_Closed,
SUM(case when EXTREF is null then 0 else 1 end) as case_Referred,
round((COUNT(case SLA_MET when 'Y' then 1 else null end)/COUNT(case CLOSED when 'Y' then 1 else null end)*100),2) as percent_SLA_met
FROM IT_SUPPORT_CALLS
GROUP BY to_char(DATELOGGED,'MON-YYYY')
) calls
LEFT JOIN
(
SELECT
SUBSTR(START_TIME, 4) as down_month,
SUM(extract(minute from DURATION) +
extract(hour from DURATION) * 60 +
extract(day from DURATION) * 60 * 24
) || 'minutes' as total_down_mins
FROM IT_DOWNTIME
WHERE duration is not null
GROUP BY SUBSTR(START_TIME, 4)
) downs
ON calls.month = downs.down_month
Changed your date formatting of the first query to be MON-YYYY to make it align with what you claim is the formatting of the varchar2 date of the second query (dd-mon-yyy), and substringed the date to remove the day, leaving just the month
Edit:
Ok, so since you've posted some different example data from IT_DOWNTIME I see the problem: there's a time on the date also. Your first sample data didn't contain this time, it was just a date (as a string) so I was doing...
SUBSTR('01-JAN-1970', 4)
...to reduce the day date to a month date ('JAN-1970') and this was intended to align with the stuff going on in the other table ( to_date() with a format of 'non-yyyy' )
Now we know that there is a time in there too, of course it won't align because...
SUBSTR('01-JAN-1970 12:34', 4)
...produces 'JAN-1970 12:34' and this will then not match to anything from the other table (which will be just 'JAN-1970' without the time), so the left join means that nulls will be output
The solution is to change the SUBSTR call so it cuts 8 characters, starting at position 4:
SUBSTR(start_time, 4, 8)
This will remove the day and the time, leaving just the month-year that we need. You'll need to make the change in two places in the query above..
Apologies for the delay on replying to this. However, that is working perfectly Caius, thanks very much! So to be complete, had to change your above code to:
SUBSTR(START_TIME, 4, 8) as down_month,
and
GROUP BY SUBSTR(START_TIME, 4, 8)

SQL sum case when between max date from table column

I am trying to sum in SQL cases when a date is between a max date minus 7 and a max date, but unable to get it right.
Example:
sum(case when date between max(date from field)-7 and max(date from field) then column to sum else 0 end) as '0-7 Days'
This may work:
I may be getting the DATEDIFFs a little bit confused but it should be something along those lines
SUM(CASE
WHEN DATEDIFF(DAY,datecolumn,DATEADD(DAY,-7,max(datecolumn)))<0 AND DATEDIFF(DAY,datecolumn,max(datecolumn))>0
THEN columntosum
ELSE 0
END) AS '0-7 Days'
In most databases, you can do something like this:
select (case when datecol >= maxdatecol - 7 and datecol <= maxdatecol then columntosum else 0
end) as days_0_7
from (select t.*,
max(datecol) over () as maxdatecol
from table t
) t;
Note that date arithmetic varies between databases, so this exact syntax may not work (small modifications should fix the problems for most databases).

Grouping by Date without Time component

So i have a table that looks like this:
As you can see some of the dates are the same however the time of day is different.
i have the following select statement (i have deleted and altered some data since this is rather sensitive):
SELECT LAST_UPD AS PERIOD,
COUNT(CASE WHEN SOLVED_SECONDS /60 /60 <= 2 THEN 1 END) as completed_within_2hours,
COUNT(CASE WHEN STATUS ='Færdig' THEN +1 END) as completed_callbacks,
COUNT(CASE WHEN SOLVED_SECONDS /60 /60 <= 2 THEN 1 END) / COUNT(CASE WHEN STATUS ='Færdig' THEN 1 END) * 100 as Percentage
FROM TABLE
WHERE LAST_UPD BETWEEN '2013-07-01' AND '2013-07-03'
AND STATUS ='Færdig'
AND AGENTGROUP IN ('Hovednumre','Forsikring','Hotline','Kunder')
GROUP BY LAST_UPD
Now i want my query to count when the DATES are the same so forexample if the date is 2013-07-01 i want it to count x amount for that day regardless of time of day.
I have tried the following:
SELECT DISTINCT TO_CHAR(LAST_UPD, 'YYYY/MM/DD') AS PERIOD,
Sadly this returns each of days but doesnt count them correctly (it returns 1 for each day).
Perhaps what you want is to select and group by "Trunc(last_upd)"