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).
Related
I have an OLTP database that contains 400 million rows. I am trying to create a SQL query that produces results something similar to this:
Count(*) DateRange Using DateDiff
1 million > 10 yrs
2 million > 20 yrs
10 Million > 50 yrs
And so on.
I create a query something like this:
select count(*) , DateDiff( year , Start_date , End_Date)
group by column
having DateDiff > 10
Union
select count(*) , DateDiff( year , Start_date , End_Date)
group by column
having DateDiff > 20
I believe there is a Cube function that I can use but I cannot seem to get that query right. Any help would be appreciated.
Having a query with aggregates on a full table takes a while. You are having n such queries, which is n times slower than if you had a single query. So, logically, we conclude that the goal is to convert your union-based query concatenation into a single query. And luckily it is achievable (I hope this is legal syntax in SQL Server, in which I didn't work for a few years, but I'm sure the idea can be used):
select yourcolumn
sum(
case
when DateDiff( year , Start_date , End_Date) > 10 then 1
else 0
end) as yrs10,
sum(
case
when DateDiff( year , Start_date , End_Date) > 20 then 1
else 0
end) as yrs20,
sum(
case
when DateDiff( year , Start_date , End_Date) > 50 then 1
else 0
end) as yrs50
from yourtable
group by yourcolumn;
So, this will create a single record for each possible value of yourcolumn and in that record you will have a field that will identify your yourcolumn value and a field for each of your time interval-based aggregation.
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;
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!!
I have done the following to get a list of count for today having a date less than today. I have done the following code:
select SUM(CASE WHEN (EXPIRYDAYE>= CONVERT(date, GETDATE())) > 1
then 1
else 0
end)
from bottles;
However, I am getting this as error:
Incorrect syntax near '>'.
Note that I need to do the count that way. So please help me on the syntax in this way of doing the count. Thanks
you have to try like below
select SUM(CASE WHEN EXPIRYDAYE< CONVERT(date, GETDATE()) then 1 else 0 end)
In your sql query case when statement is wrong
CASE WHEN (EXPIRYDAYE>= CONVERT(date, GETDATE())) > 1 -- here last >1 is illogical
Try this
SELECT
SUM(
CASE WHEN EXPIRYDAYE< CAST(GETDATE() AS DATE)
THEN 1
ELSE 0 END)
You don't need the > symbol before the 1
Following simple query should work for your case. You don't need CASE WHEN for this.
SELECT COUNT(*) TotalCount
FROM YOUR_TABLE WHERE EXPIRYDAYE < CAST(GETDATE() AS DATE)
Note that I need to do the count that way. So please help me on the
syntax in this way of doing the count.
I am not sure why you want to do it in a specific way whereas more efficient query is available.
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;