We have 6 Columns at SQL Server table SLA
I tried to add compained column QASLA from the below
Created - Closed Columns are datetime - Not NULL
EsculationDate - [EsculationFeedback]
[InternalEsculationReplay] - [InternalEsculationDate] Columns are
datetime type and Could be NULL values
alter table SLA
add QASLA as
iif((Closed=null),datediff(dd,getdate(),Created),
(datediff(dd,Closed,Created))-datediff(dd,IIF(COALESCE ([EsculationDate],0)>COALESCE ([InternalEsculationDate],0),COALESCE ([InternalEsculationDate],0),COALESCE ([EsculationDate],0)),
IIF(COALESCE ([EsculationFeedback],0)>COALESCE ([InternalEsculationReplay],0),COALESCE ([EsculationFeedback],0),COALESCE ([InternalEsculationReplay],0))))
When i try to insert a new record
insert into [dbo].[SLA]
([Created],[EsculationDate],[EsculationFeedback],[Closed])
values('10-Jun-15','10-Jun-15','15-Jun-15','15-Jun-15')
QASLA Result = -42173
I need to get value 0 as created date = 10 Jun and Closed Date = 15 Jun mins (EsculationDate+EsculationFeedback)
I try to use ISNULL also
Not quite sure I understand your question but you IIF is useless here because it will never be equal to NULL. You cannot compare a value to NULL and must use IS NULL:
alter table SLA
add QASLA as
iif((Closed is null),datediff(dd,getdate(),Created),
(datediff(dd,Closed,Created))-datediff(dd,IIF(COALESCE ([EsculationDate],0)>COALESCE ([InternalEsculationDate],0),COALESCE ([InternalEsculationDate],0),COALESCE ([EsculationDate],0)),
IIF(COALESCE ([EsculationFeedback],0)>COALESCE ([InternalEsculationReplay],0),COALESCE ([EsculationFeedback],0),COALESCE ([InternalEsculationReplay],0))))
Some of your DATEDIFF statements appear to have the dates the "wrong way around". You should have the earlier date as the second argument and the later date as the third argument to return the positive days between them.
Also, you are treating NULL dates as 0 in many cases, where 0 will be interpreted as a "very early date".
I would have expected your handling of NULLs to work very differently here? You can't use equality comparison between a column and NULL, you need to use the IS NULL statement instead, e.g. "Closed = NULL" becomes "Closed IS NULL".
Finally, you say Closed Date is NOT NULL, but the very first thing you do in your script is to compare it to NULL.
Related
I'm wondering if there's a SQL clause for "date is not before"?
I don't want date greater than, because some of my values are blank, and I want the clause to capture those blank values.
So basically, date not before 17/03/2021 would bring back a count of "27".
date
count
16/03/2021
5
17/03/2021
4
18/03/2021
12
blank
11
Many thanks,
Nam
I would suggest using a where clause something like the following...
WHERE (Date >= '20210317' OR Date IS NULL)
Let me assume that "blank" means NULL. In Standard SQL, you need an explicit comparison for this. And you need a date constant:
where "date" >= date '2021-03-17' or "date" is null
You can also use coalesce():
where coalesce("date", '2199-12-31') >= date '2021-03-17'
but this can prevent the optimizer from choosing the best execution plan.
This question already has answers here:
How can I include null values in a MIN or MAX?
(7 answers)
Closed 4 years ago.
I am working on a SQL query to pull the minimum begin and maximum end date for recurring classes. The way the database is set up, If the classes are not continuing they have an end date, if the classes are continuing then the end date is null. The field is Data Type datetime.
If the end date is null that is essentially the date I want because it is the maximum end date but I cannot seem to work out how to get that to work? I get whatever the last actual date in that field is and cannot get the query to return either null or better yet a default date that I set.
Thanks in advance
If you want the null date as the max, you can do so with a case expression:
select (case when count(*) = count(enddate) then max(enddate) end)
The count(*) = count(enddate) basically says that none of the enddate values are NULL.
If you like playing around with functions, you can also use:
select nullif(max(coalesce(enddate, '9999-01-01')), '9999-01-01')
But I prefer the first method.
I have a table storing a datetime column, which is indexed. I'm trying to find a way to compare ONLY the month and day (ignores the year totally).
Just for the record, I would like to say that I'm already using MONTH() and DAY(). But I'm encountering the issue that my current implementation uses Index Scan instead of Index Seek, due to the column being used directly in both functions to get the month and day.
There could be 2 types of references for comparison: a fixed given date and today (GETDATE()). The date will be converted based on time zone, and then have its month and day extracted, e.g.
DECLARE #monthValue DATETIME = MONTH(#ConvertDateTimeFromServer_TimeZone);
DECLARE #dayValue DATETIME = DAY(#ConvertDateTimeFromServer_TimeZone);
Another point is that the column stores datetime with different years, e.g.
1989-06-21 00:00:00.000
1965-10-04 00:00:00.000
1958-09-15 00:00:00.000
1965-10-08 00:00:00.000
1942-01-30 00:00:00.000
Now here comes the problem. How do I create a SARGable query to get the rows in the table that match the given month and day regardless of the year but also not involving the column in any functions? Existing examples on the web utilise years and/or date ranges, which for my case is not helping at all.
A sample query:
Select t0.pk_id
From dob t0 WITH(NOLOCK)
WHERE ((MONTH(t0.date_of_birth) = #monthValue AND DAY(t0.date_of_birth) = #dayValue))
I've also tried DATEDIFF() and DATEADD(), but they all end up with an Index Scan.
Adding to the comment I made, on a Calendar Table.
This will, probably, be the easiest way to get a SARGable query. As you've discovered, MONTH([YourColumn]) and DATEPART(MONTH,[YourColumn]) both cause your query to become non-SARGable.
Considering that all your columns, at least in your sample data, have a time of 00:00:00 this "works" to our advantage, as they are effectively just dates. This means we can easily JOIN onto a Calendar Table using something like:
SELECT dob.[YourColumn]
FROM dob
JOIN CalendarTable CT ON dob.DateOfBirth = CT.CalendarDate;
Now, if we're using the table from the above article, you will have created some extra columns (MonthNo and CDay, however, you can call them whatever you want really). You can then add those columns to your query:
SELECT dob.[YourColumn]
FROM dob
JOIN CalendarTable CT ON dob.DateOfBirth = CT.CalendarDate
WHERE CT.MonthNo = #MonthValue
AND CT.CDay = #DayValue;
This, as you can see, is a more SARGable query.
If you want to deal with Leap Years, you could add a little more logic using a CASE expression:
SELECT dob.[YourColumn]
FROM dob
JOIN CalendarTable CT ON dob.DateOfBirth = CT.CalendarDate
WHERE CT.MonthNo = #MonthValue
AND CASE WHEN DATEPART(YEAR, GETDATE()) % 4 != 0 AND CT.CDat = 29 AND CT.MonthNo = 2 THEN 28 ELSE CT.Cdat END = #DayValue;
This treats someone's birthday on 29 February as 28 February on years that aren't leap years (when DATEPART(YEAR, GETDATE()) % 4 != 0).
It's also, probably, worth noting that it'll likely be worth while changing your DateOfBirth Column to a date. Date of Births aren't at a given time, only on a given date; this means that there's no implicit conversion from datetime to date on your Calendar Table.
Edit: Also, just noticed, why are you using NOLOCK? You do know what that does, right..? Unless you're happy with dirty reads and ghost data?
I have an SQL statement:
UPDATE informix.dv_billing dv
SET dv.fee = CASE WHEN ((SELECT dc.mm_discount
FROM dv_mm_disc dc
WHERE dc.year = YEAR(dv.tdate)
AND dc.quarter = quarter(dv.tdate)
AND dc.bid=dv.bid
AND dc.mm_code=dv.pcode
AND dc.ins=dv.ins) = 0)
THEN dv.fee ELSE 0
END
WHERE MDY(MONTH('2012-04-05'), 1, YEAR('2012-04-05')) - 2 UNITS MONTH
AND last_day(DATE('2012-04-05'))
;
The SQL returns the error:
Result of a boolean expression is not of boolean type.
What could be wrong?
I think you're running into problems with the outer (main) WHERE clause.
You have a condition that is nominally:
WHERE expr1 AND expr2
which requires both expr1 and expr2 to be boolean expressions, but the actual expressions are not booleans — hence the slightly oddly worded error message.
The expression:
MDY(MONTH('2012-04-05'), 1, YEAR('2012-04-05')) - 2 UNITS MONTH
gives a DATE (or possibly DATETIME YEAR TO DAY) result. It is reasonable to hypothesize that the last_day() function returns the date of the last day in the month containing the given date.
Maybe that last AND should be =?
WHERE MDY(MONTH('2012-04-05'), 1, YEAR('2012-04-05')) - 2 UNITS MONTH = last_day(DATE('2012-04-05'))
That could be abbreviated to:
WHERE MDY(4, 1, 2012) - 2 UNITS MONTH = last_day(DATE('2012-04-05'))
I'm not sure when that condition would ever map to true...but that is a separate discussion. I do recognize that the '2012-04-05' is likely a query parameter, simplified for the purpose of asking the question, so the abbreviation is not general in valid, but I seems unlikely that the first day of a month will ever be the last day of any month (but a lot hinges on what is in that last_day() function).
I have previously asked the following question: Calculating percentage within the SQL
Now i was lucky enough to get a great answer however in my question i did not take into account that my rows could contain zero.
The questions row where simple:
select
Number_of_Calls,
Number_of_Answered,
((Number_of_answered/Number_Of_Calls)*100) as answer_percent,
Date
from table Where Date BETWEEN '2012-09-10' AND '2012-09-11'
However Number_of_answered could be zero (if our company did not answer the calls) so if i want the full number in percentage how do i take 0 into account?
By the way. The database that we use is an Oracle database with PL SQL
The nullif function can be used to return null if the divisor is zero. When SQL encounters a null divisor it forces the entire equation to return null, preventing your error from occurring.
select
Number_of_Calls,
Number_of_Answered,
((Number_of_answered/nullif(Number_Of_Calls,0))*100) as answer_percent,
Date
from table Where Date BETWEEN '2012-09-10' AND '2012-09-11'
If you would like to exclude null percentages use the following SQL:
select * from(select
Number_of_Calls,
Number_of_Answered,
((Number_of_answered/nullif(Number_Of_Calls,0))*100) as answer_percent,
Date
from table Where Date BETWEEN '2012-09-10' AND '2012-09-11') alias
where answer_percent is not null;
Case when Number_Of_Calls = 0
THEN 0 --or your desired value, maybe 100
else (Number_of_answered/Number_Of_Calls)*100
END as answer_percent
i think you mean "Number_Of_Calls" could be zero (thus raising a zero_divide error?) if so do
case Number_Of_Calls when 0 then 0 else ((Number_of_answered/Number_Of_Calls)*100) as answer_percent
As far as I understood you from your comment you want a rate of answered calls over a period of time, including days when 100% calls were unanswered.
I guess the simpliest approach would be
select sum(number_of_answered) / sum (number_of_calls)
from table
where date between interval_start and interval_end
in this case.