Sybase TSQL: exists reports positive even if the result is null - sybase

I do not expect function exists to report positive (i.e. returns true so "there is trade" is printed) when there is no data between the two future dates I picked at random
if exists(select min(dt_txn) from SOME_TRADE where dt_txn > '1 Mar 2013' and dt_txn < '8 Mar 2013'
begin
print 'There is trade'
end
If I just run the select statement alone, it will return a null.
What is the proper way to use exist in this context?

Try this way:
if exists(select 1 from SOME_TRADE where dt_txn > '1 Mar 2013' and dt_txn < '8 Mar 2013')
begin
print 'There is trade'
end

Related

Case when only executes ELSE statement

I have never seen this happen before, but when I SELECT a CASE WHEN statement in SQL Server, it executes the ELSE statement. How is this possible? Is it because it cannot handle different kind of value types in the same column?
SELECT CASE WHEN len(birthDate)=4 THEN birthDate
WHEN birthDate = '' THEN ''
ELSE CONVERT(datetime, birthDate)
END AS [birthDateConverted]
,[birthDate]
FROM BirthDayTable
The result looks like this:
birthDateConverted birthDate
1951-01-01 00:00:00.000 1951
1936-06-19 00:00:00.000 June 19, 1936
1948-03-11 00:00:00.000 March 11, 1948
NULL
I want to have the following:
birthDateConverted birthDate
1951 1951
1936-06-19 June 19, 1936
1948-03-11 March 11, 1948
NULL
And I also do not understand why I get NULL when I specify ''. But this part is not as important as the first part, as I would like to have only the year when only a year is specified.
Try this first and then implement the logic accordingly in your query.
Replace #birthDate variable with the input string that you desire.
There is one more check that you can perform using ISDATE() function which checks if the entered string is a valid date and you can change your logic accordingly if required.
More information about isdate() function can be found here
DECLARE #birthDate varchar(20)=''
SET #birthDate='March 11, 1948'
SELECT CASE WHEN len(#birthDate)=4 THEN CONVERT(varchar, #birthDate)
WHEN CONVERT(varchar,#birthDate) = '' THEN ''
ELSE CONVERT(varchar,CONVERT(date, #birthDate))
END AS [birthDateConverted]
NULL is not equal to '' so, you can do instead :
SELECT (CASE WHEN len(birthDate) = 4
THEN birthDate
WHEN birthDate IS NULL
THEN ''
ELSE CONVERT(datetime, birthDate)
END) AS [birthDateConverted],
[birthDate]
FROM BirthDayTable;
However, '' will implicit convert into datetime.
You are trying to store multiple types in one column which is not possible in SQL. So when the query executes on SQL Server it will type all the values on first read type.
In your case, your second conditions always fail due to comparing a null value with an empty string, in SQL you can achieve this through ISNULL(birthDate,'') = '' so when the value is null or empty it always returns true.
So you can't set an empty string or date string with DateTime value your requirement is invalid.
I think you are looking for this it will format DateTime values as string
SELECT (CASE WHEN ISDATE(birthDate) = 1
THEN CONVERT(varchar, CONVERT(datetime,birthDate), 110)
ELSE birthDate
END) AS [birthDateConverted], [birthDate]
FROM BirthDayTable;
I have tried the following, which works for my case. Hopefully someone else can benefit from it too
SELECT CASE WHEN len(birthDate)>4
THEN CONCAT(YEAR(birthDate), '-', RIGHT('00' + CONVERT(NVARCHAR(2), DATEPART(MONTH, (birthDate))),2), '-',
RIGHT('00' + CONVERT(NVARCHAR(2), DATEPART(DAY, (birthDate))),2))
WHEN len(birthDate)=4
THEN CONVERT(nvarchar(255), birthDate)
ELSE ''
END AS [birthDateConverted]
,[birthDate]
FROM BirthDayTable;
A CASE will only return 1 datatype.
In your SQL that would return a DATETIME because of that convert.
And since '1951' is then implicitly casted to a DATETIME, it returns '1951-01-01 00:00:00.000'.
So let the CASE return a VARCHAR.
If you're using MS SQL Server 2012 or higher, then you could use TRY_CONVERT to verify if the varchar can be converted to a date or datetime.
Because a TRY_CONVERT will return NULL when the conversion attempt fails.
Example snippet:
select *,
(case
when birthDate like '[0-9][0-9][0-9][0-9]' then birthDate
when birthDate like '%[0-9]%' and try_convert(date, birthDate) is not null
then convert(varchar(10), convert(date, birthDate), 20)
else ''
end) as birthDateConverted
from (values
(1,'1951'),
(2,'June 19, 1936'),
(3,'March 11, 1948'),
(4,''),
(5,null),
(6,'ABCD')
) t(id, birthDate);
Returns:
id birthDate birthDateConverted
-- -------------- ------------------
1 1951 1951
2 June 19, 1936 1936-06-19
3 March 11, 1948 1948-03-11
4
5 NULL
6 ABCD

Stored Procedure to check if four weeks with less then two records

I am working on a stored procedure. The input is going to be a date and ID and the procedure is going to set a value to true if there are 4 weeks with less then 2 inputs per week.
It has to take in consideration that I might pass an early date with no records in the database.
I couldn't format the code. I don't know why?
So far I got that with previous help from you guys:
CREATE proc [dbo].[sp_test] (#id int, #d date)
as
declare #WeekFirstRecord as int
declare #WeeksWithNoRecords as int
SET #WeekFirstRecord = datepart(week,(select Min(ZeroPointIncidentDate) from EmployeeZeroPointIncidents where ZeroPointIncidentDate > #d))
SET #WeeksWithNoRecords = datepart(week, #WeekFirstRecord) - datepart(week, #d)
select case when sum(c) + #WeeksWithNoRecords >= 4 then 'true' else 'false' end status
from (
select c = count(*) over (partition by EmpId, datepart(week, ZeroPointIncidentDate))
from EmployeeZeroPointIncidents
where EmpId = #id and ZeroPointIncidentDate >= #d
) a
where c = 1
In my data only the weeks with the stars have less than two inputs and if I pass the date 7-7-2015 is going to set the output value to true
Any help will be appreciated. Do I need to iterate through every record and set a counter if less then two inputs or there is an easier way ?
ID Date
1 7-7-2015
2 6-23-2015
3 6-12-2015
1 7-8-2015
1 7-14-2015 *
1 7-21-2015 *
1 7-27-2015
1 7-28-2015
1 7-29-2015
1 7-30-2015
1 8-3-2015 *
1 8-11-2015 *
If I had week Jul 13 - no records week Jul 20 - no records week Jul 27 - 2 records Week Aug 3 - no records Week Aug 10 - 2 records Week Aug 17 - no records And pass Jul 12 date should return true, if I pass jul 15 should return false
I had to see your sample data set from your last question along with explanation from your last question as well as the explanation given in this question to come up with this solution.
When you ask a question here put yourself in the reader's shoes and see if the question makes any sense, anyway I hope this solution will get you what you want. cheers
CREATE PROCEDURE get_output
#Date DATE
,#ID INT
,#Output INT OUTPUT -- 1 true , 0 false
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Count INT;
SELECT #Count = COUNT(*)
FROM TableName
WHERE CAST(DATEADD(WEEK, DATEDIFF(WEEK, 0, #Date), 0) AS DATE)
= CAST(DATEADD(WEEK, DATEDIFF(WEEK, 0, [Date]), 0) AS DATE)
AND ID = #ID
GROUP BY CAST(DATEADD(WEEK, DATEDIFF(WEEK, 0, [Date]), 0) AS DATE)
IF (#Count < 2)
SET #Output = 1;
ELSE
SET #Output = 0;
END

Date Range Limitations SQL Server

I am wanting to limit the user to not be able to search for a time frame longer than a year. So 1/1/2014 to 1/1/2015 is valid, but 1/1/2014 to 3/1/2015 is not valid. They are inputting the dates in a date picker in a SSRS report.
WHERE "view"."myDate" between #firstDate and #secondDate
Is there logic I can put in the WHERE cause that can put these restrictions into affect?
You could add a DATEDIFF check to the WHERE clause to limit the range to a year;
AND DATEDIFF(d, #firstDate, #secondDate) < 366
However, this will return nothing if the range exceeds a year. If you want the query to return upto a years worth of results then you could use something like this;
WHERE "view"."myDate" between #firstDate and
CASE
WHEN DATEDIFF(d, #firstDate, #secondDate) < 366 THEN #secondDate
ELSE DATEADD(d, 365, #firstDate)
END
If you want to raise an error if the user provides an invalid range then you would have to use a stored procedure for your data source and perform parameter validation. Something like this;
CREATE PROC dbo.GetMyData ( #firstDate date, #secondDate ) AS
BEGIN
IF (DATEDIFF(d, #firstDate, #secondDate) > 365)
BEGIN
RAISERROR('Please restrict searches to less than a year.', 16, 1)
RETURN
END
SELECT ...
WHERE "view"."myDate" between #firstDate and #secondDate
END

Get all quarters in Month, Year format between two dates

I have two dates say '2011-01-23' and '2015-11-29',
'2011-01-23' falls in first quarter of 2011 so 'Jan 2011'
'2015-11-29' falls in fourth quarter of 2015 so 'Oct 2015'
In SQL Server I want get all quarters in a select list.
e.g.
Input: #StartDate='2011-01-23' , #EndDate='2015-11-29'
Output:
Jan 2011
Apr 2011
Jul 2011
Oct 2011
Jan 2012
Apr 2012
Jul 2013
Oct 2013
Jan 2014
......
......
......
Jul 2015
Oct 2015
You can use a recursive CTE to generate the dates as follows:
declare #StartDate datetime
declare #EndDate datetime
select #StartDate='2011-01-23' , #EndDate='2015-11-29'
;With Quarters as (
select DATEADD(quarter,DATEDIFF(quarter,0,#StartDate),0) as dt
union all
select DATEADD(quarter,1,dt)
from Quarters
where dt < DATEADD(quarter,DATEDIFF(quarter,0,#EndDate),0)
)
select
--I'd usually keep them as dates at this point, but to match your requirement
CONVERT(varchar(3),dt,109) + ' ' + CONVERT(varchar(4),dt,120)
from Quarters order by dt
This also uses a couple of other tricks - it uses CONVERT with far too short target datatypes to quickly truncate the strings to just the parts that we want to keep - and it uses a DATEADD/DATEDIFF pair to quickly round a datetime value down to it's nearest interval boundary.
For SQL Server 2012, you could instead use FORMAT to produce the output string, but I've not experimented with that much so I'll leave that as an exercise...
Finally, I found the solution of my question..
WITH mycte AS
(
SELECT CAST('2011-01-01' AS DATE) DateValue
UNION ALL
SELECT DATEADD(Q,1,DateValue) FROM mycte WHERE DATEADD(Q,1,DateValue) < '2012-12-31'
)
SELECT CONVERT(varchar(3), DATENAME(MONTH,DateValue))+ ' ' +Convert(varchar(4),DATEPART(YYYY,DateValue)) FROM mycte OPTION (MAXRECURSION 0)

SQL Server: Group results on time interval

I've got an MS SQL Server table that records our plant's alarm events with a row for each alarm and a datetime column to capture when the alarm happened.
We run our plant in 12 hour shifts (6 am to 6pm, 6pm to 6am) and I need to figure out how many alarms we're getting each shift. How do I group my results to get that?
The original table looks something like this:
DateTime Alarm Name
2010-01-05 14:32:22 Overpressure
2010-01-05 21:32:59 Underspeed
2010-01-06 05:58:13 Underspeed
2010-01-06 06:02:46 Machine Current Fault
And we need to group the results something like this:
Date Shift Count
2010-01-05 Day 1
2010-01-05 Night 2
2010-01-06 Day 1
Note that if alarms happen between 6 pm on say Jan 5th and 6 am on Jan 6th, they all get counted as Night Shift from Jan 5th.
Any advice?
In this solution, I work out the shift start/end times by subtracting 6 hours from the event time.
DECLARE #t TABLE
([DateTime] DATETIME
,[Alarm Name] VARCHAR(30)
)
INSERT #t
SELECT '2010-01-05 14:32:22','Overpressure'
UNION SELECT '2010-01-05 21:32:59','Underspeed'
UNION SELECT '2010-01-06 05:58:13','Underspeed'
UNION SELECT '2010-01-06 06:02:46','Machine Current Fault'
SELECT CONVERT(CHAR(10),DATEADD(hh,-6,[DateTime]),120) AS date
,CASE WHEN DATEPART(hh,DATEADD(hh,-6,[DateTime])) < 12
THEN 'day'
ELSE 'night'
END AS shift
,COUNT(1) AS cnt
FROM #t
GROUP BY CONVERT(CHAR(10),DATEADD(hh,-6,[DateTime]),120)
,CASE WHEN DATEPART(hh,DATEADD(hh,-6,[DateTime])) < 12
THEN 'day'
ELSE 'night'
END
order by 1,2

Resources