Remove negative values - sql

I have a certain query that obtains derived values
select datediff(minute, date_field_1, date_field_2) as date_diff from table_name;
The problem is that some of the values in the result can be negative as date_field_1 can be greater than date_field_2 in some cases.
So this results in negative, along with positive values in the resultant table.
Is there anyway to put some default values or omit and give null or zero in those negative calculated values ?
Using redshift.

One way to catch negative values would be to use CASE WHEN. It checks whether your datediff is smaller than 0.
I proposed 0 as default value:
SELECT
CASE WHEN datediff(minute, date_field_1, date_field_2) < 0
THEN 0
ELSE datediff(minute, date_field_1, date_field_2) END as date_diff
FROM table_name;

Is this what you want?
select (case when date_field_1 >= date_field_2
then datediff(minute, date_field_1, date_field_2)
else 0
end) as date_diff
from table_name;

Related

Multiple conditions in select statement based on values

I have a multiple ctes. In my select statement I must filter values base on the conditions. This is my query.
SELECT roadName
,sum(roadLength) AS sumRoadLength
,avg(elevationDifference) AS eglAvgDepth
,avg(elevationDifference) AS pglAvgDepth
,
FROM cte3
GROUP BY roadName
ORDER BY roadName
Under "elevationDifference" there are lots of values ranging from -10 to +20 which are spread through "roadName". What i want to accomplished is that "eglAvgDepth" will return if all "elevationDifference" values are <0 and take the average. Same case with pglAvgDepth where values are >0.
I tried to add where statement but works only in eglAvgDepth
WHERE elevationDifference < 0
GROUP BY roadName
ORDER BY roadName
Just add a conditional expression:
avg(case when elevationDifference < 0 then elevationDifference end) as eglAvgDepth,
avg(case when elevationDifference > 0 then elevationDifference end) as pglAvgDepth,
EDIT:
You have phrased this that you want the value based on whether all the values are positive or negative. If so:
(case when max(elevationDifference) < 0 then avg(elevationDifference) end) as eglAvgDepth,
(case when max(elevationDifference) > 0 then avg(elevationDifference) end) as pglAvgDepth,

SQL Server CASE Statement Evaluate Expression Once

I may be missing something obvious! Thanks in advance for any help.
I am trying to use a CASE statement in an inline SQL Statement. I only want to evaluate the expression once, so I am looking to put the expression in the CASE section, and then evaluate the result in each WHEN. Here is the example:
SELECT
MyTable.ColumnA,
CASE DateDiff(d, MyTable.MyDate, getDate())
WHEN <= 0 THEN 'bad'
WHEN BETWEEN 1 AND 15 THEN 'reasonable'
ELSE 'good'
END as MyCalculatedColumn,
MyTable.SomeOtherColumn
I know I can do this:
CASE
WHEN DateDiff(d, MyTable.MyDate, getDate()) <= 0 THEN 'bad'
WHEN DateDiff(d, MyTable.MyDate, getDate()) BETWEEN 1 AND 15 THEN 'reasonable'
ELSE 'good'
END
But in my first example, SQL does not seem to like this statement:
WHEN <= 0 THEN 'bad'
Note that the statement is inline with other SQL, so I can't do something like:
DECLARE #DaysDiff bigint
SET #DaysDiff = DateDiff(d, MyTable.MyDate, getDate())
CASE #DaysDiff
WHEN <= 0 THEN 'bad'
WHEN BETWEEN 1 AND 15 THEN 'reasonable'
ELSE 'good'
END
My actual DateDiff expression is much more complex and I only want to maintain its logic, and have it evaluated, only once.
Thanks again...
You can use apply for this purpose:
SELECT MyTable.ColumnA,
(CASE WHEN day_diff <= 0 THEN 'bad'
WHEN BETWEEN 1 AND 15 THEN 'reasonable'
ELSE 'good'
END) as MyCalculatedColumn,
MyTable.SomeOtherColumn
FROM MyTable CROSS APPLY
(VALUES (DateDiff(day, MyTable.MyDate, getDate()))) v(day_diff)
APPLY is a very handy way to add calculated values into a statement. Because they are defined in the FROM clause, they can be used in SELECT, WHERE, and GROUP BY clauses where column aliases would not be recognized.
I see your problem. CASE expression WHEN value can only do an equality check
You could try using a CTE (Common Table Expression), do everything except the case statement in the CTE and then put the CASE in the final SELECT at the end. I'm not sure whether it will prevent the expression being evaluated twice - thats kindof the optimisers problem, not yours (thats how I like to think about it)
WITH cteMyComplexThing AS(
SELECT MyTable.ColumnA,
DateDiff(d, MyTable.MyDate, getDate()) as ComplexThing,
MyTable.SomeOtherColumn
FROM MyTable
)
SELECT
ColumnA,
CASE
WHEN ComplexThing <= 0 THEN 'bad'
WHEN ComplexThing BETWEEN 1 AND 15 THEN 'reasonable'
ELSE 'good'
END as MyCalculatedColumn,
SomeOtherColumn
FROM cteMyComplexThing
The WHEN clause in a CASE statement needs both sides of the condition. <=0 cannot stand by itself.
CASE #DaysDiff
WHEN ? <= 0 THEN 'bad'
WHEN BETWEEN 1 AND 15 THEN 'reasonable'
ELSE 'good'
END

How to write a sql query if order time is greater then 24:00:00 than 1 otherwise 0?

Order Time
00:36:06
02:21:59
04:53:57
05:52:38
00:29:11
17:53:29
00:17:03
02:03:20
01:24:02
00:09:43
00:20:55
02:53:30
00:32:26
07:45:31
09:11:37
00:19:17
92:11:21
00:19:08
00:10:50
02:46:05
How to write a sql query if order time is greater then 24:00:00 than 1 otherwise 0?
Presumably, ordertime is a string. You can do this as:
select (case when ordertime > '24:00:00' then 1 else 0 end)
Assuming that in some magic way you were able to insert 92:11:21 into a time column, use this calculated column in your query:
CASE WHEN DATEDIFF(second, 0, [Order Time]) > 86400
THEN 1
ELSE 0
END AS GreaterThan24h

TSQL Counting with Nulls

I have a table what counts admited and discharge from ED. This is what the table looks like
I'm trying to get the total admitted and discharged. Something like
Admitted - 100
Discharge - 200
Is there a way to do that with the NULL values?
select
sum(case when Admitted is null then 0 else Admitted end) Admitted,
sum(case when DischargedFromED is null then 0 else DischargedFromED end) as DischargedFromED
from MyMagicalTable;
or
select
sum(coalesce(Admitted, 0)) Admitted,
sum(coalesce(DischargedFromED, 0)) DischargedFromED
from MyMagicalTable;
Just use sum();
select sum(admitted) as admitted, sum(DischargedFromED) as DischargedFromED
from t;
Aggregation functions ignore NULL values.
If you are concerned about NULL values appearing after the sum(), then use coalesce() afterwards:
select coalesce(sum(admitted), 0) as admitted,
coalesce(sum(DischargedFromED), 0) as DischargedFromED
from t;
The above assumes that the columns are numeric. If they are some other type, they need to be converted to numbers.

Average without calculate zero

I have some fields in the table, need to average those fields.
Then I run this syntax, because I don't want to calculate 0 (zero) value.
SELECT myDate, AVG(CASE myField1 WHEN 0 THEN NULL ELSE myField1 END) AS avgmyField1
FROM myTable WHERE myDate = '2014-06-01'
On my syntax, the average calculation means.. Make zero value to null.
My question is, How if all values are zero...?
Thank you.
Then you get NULL.
If you want zero instead, use COALESCE:
COALESCE( AVG(CASE myField1 WHEN 0 THEN NULL ELSE myField1 END) , 0)
Average will not use nullvalues to calculate an average value
IsNull or Coalesce can be used to change null values to different values.
This script will change 0 to null and take the average value:
SELECT IsNull(AVG(NullIf(val,0)), 0)
FROM
(Values(5),(7),(0)) tbl(val)
Since 0 is excluded the result is 6
You could also do this:
SELECT myDate, COALESCE(AVG(myField1), 0) AS avgmyField1
FROM myTable WHERE myDate = '2014-06-01' and myField1 <> 0