IsNumeric Time value problem - sql-server

Table1
Time
10:00:00
12:00:00
Absent
14:00:00
Holiday
...,
Time column Datatype is varchar
I want to check the time column value is numeric then 'Present'
Tried Query
Select case when isnumeric(time) then 'Present' else time end as time from table1
Showing error in 'then'
How to modify my query according to my requirement
Need Query Help

Try using ISDATE
Returns 1 if the expression is a valid
date, time, or datetime value;
otherwise, 0.
Something like
DECLARE #Table TABLE(
[Time] VARCHAR(50)
)
INSERT INTO #Table SELECT '10:00:00'
INSERT INTO #Table SELECT '12:00:00'
INSERT INTO #Table SELECT 'Absent'
INSERT INTO #Table SELECT '14:00:00'
INSERT INTO #Table SELECT 'Holiday'
SELECT *,
ISDATE(Time),
case when ISDATE(time) != 0 then 'Present' else time end
FROM #Table

Related

Ignoring rows within daterange

I have the following data:
CREATE TABLE SampleData
(
orderid int,
[name] nvarchar(1),
[date] date
);
INSERT INTO SampleData
VALUES
(1, 'a', '2017-01-01'),
(2, 'a', '2017-01-05'),
(3, 'a', '2017-02-01'),
(4, 'a', '2017-04-01'),
(5, 'a', '2017-10-01'),
(6, 'b', '2017-04-01');
I need to retrieve each new order according to the following rules:
The first date for a name is the 'current order' for that name
Orders with the same name, but less than 3 months difference with the 'current order' is considered the same order and needs to be ignored
3 months or more difference with the 'current' order is considered a new order and is now the 'current order' (in the SampleData orderid 1 and 4 need to be compared instead of 3 and 4, because 3 is not the current order)
If the name and date are the same, then the row with the lowest orderid is the superior order
So with the sample data I need the following result:
id name, date
1 a 2017-01-01
4 a 2017-04-01
5 a 2017-10-01
6 b 2017-04-01
I tried several approaches, but without success. Any idea's on how I can achieve this?
Below is a quick fix solution that can be built upon if your code scales beyond the sample data provided. I will state beforehand that this isn't the prettiest solution but it does return the result set you indicated you were after.
If anything, you may want to consider looking into T-SQL Window Functions as well as Analytic Functions. I will advice that that they don't play well with all datatypes.
My goal with the solution below was to rank the rows while partitioning by name and order by the date field. Thus you have something similar to your order id but the rank is specific to the customer who placed the order.
I'll do my best to answer any questions:
if object_id('tempdb..#tmp_SampleData','u') is not null
drop table #tmp_SampleData
CREATE TABLE #tmp_SampleData
(
orderid int,
[name] nvarchar(1),
[date] date
);
INSERT INTO #tmp_SampleData
VALUES
(1, 'a', '2017-01-01'),
(2, 'a', '2017-01-05'),
(3, 'a', '2017-02-01'),
(4, 'a', '2017-04-01'),
(5, 'a', '2017-10-01'),
(6, 'b', '2017-04-01');
if object_id('tempdb..#tmp_iter','u') is not null
drop table #tmp_iter
select
orderid
,name
,date
,rank() over (partition by name order by date) [Rank]
,lag(orderid,1,0) over (partition by name order by date) [LagRank]
--,rank() over (partition by name order by date desc) [ReverseRank]
into #tmp_Iter
from #tmp_SampleData
if object_id('tempdb..#tmp_final','u') is not null
drop table #tmp_final
select
i.orderid
,i.name
,i.date
,datediff(month,i.date,i2.date) [MonthsPassed]
into #tmp_final
from #tmp_Iter i
left join #tmp_Iter i2
on i.Rank = i2.LagRank
select *
from #tmp_final
where 1=1
and MonthsPassed > 3
or MonthsPassed = 0
or MonthsPassed < 0
or MonthsPassed is null
#SQLUser44, thanks for your input. Unfortunately your code is not working. The result for the table below should be orderid's 1,6,7,8 and 9. Yours results in 1,2,3,5,6,7,8 and 9.
INSERT INTO #tmp_SampleData
VALUES
(1,'a','2017-01-01'),
(2,'a','2017-01-08'),
(3,'a','2017-05-01'),
(4,'a','2017-01-05'),
(5,'a','2017-02-01'),
(6,'b','2017-01-01'),
(7,'b','2017-09-01'),
(8,'c','2017-10-01'),
(9,'a','2017-04-01');
I came up with the following that works, but I think it will lack performance...
if object_id('tempdb..#tmp_SampleData','u') is not null
drop table #tmp_SampleData
CREATE TABLE #tmp_SampleData
(
orderid int,
[name] nvarchar(1),
[date] date
);
INSERT INTO #tmp_SampleData
VALUES
(1,'a','2017-01-01'),
(2,'a','2017-01-08'),
(3,'a','2017-05-01'),
(4,'a','2017-01-05'),
(5,'a','2017-02-01'),
(6,'b','2017-01-01'),
(7,'b','2017-09-01'),
(8,'c','2017-10-01'),
(9,'a','2017-04-01');
DECLARE Test_Cursor CURSOR FOR
SELECT * FROM #tmp_SampleData ORDER BY [name], [date];
OPEN Test_Cursor;
DECLARE #orderid int;
DECLARE #name nvarchar(255);
DECLARE #date date;
FETCH NEXT FROM Test_Cursor INTO #orderid, #name, #date;
DECLARE #current_date date = #date;
DECLARE #current_name nvarchar(255) = #name;
DECLARE #listOfIDs TABLE (orderid int);
INSERT #listOfIDs values(#orderid);
WHILE ##FETCH_STATUS = 0
BEGIN
IF(#name = #current_name AND DATEDIFF(MONTH, #current_date, #date) >= 3)
BEGIN
SET #current_date = #date
INSERT #listOfIDs values(#orderid)
END
IF(#name != #current_name)
BEGIN
SET #current_name = #name
SET #current_date = #date
INSERT #listOfIDs values(#orderid)
END
FETCH NEXT FROM Test_Cursor INTO #orderid, #name, #date;
END;
CLOSE Test_Cursor;
DEALLOCATE Test_Cursor;
SELECT * FROM #tmp_SampleData WHERE orderid IN (SELECT orderid FROM #listOfIDs);
Better performing alternatives are very welcome!

CONVERT on only NOT NULL records

I am working in SQL Server 2008. I have a table with two columns that store date values, but the columns themselves are varchar. (I know, this is bad practice, but I don't own the table.) Some of the records in these two columns are NULL. I am trying to do a comparison of the two columns against each other. So, to enable the comparison, I need to do a CONVERT. But, CONVERT fails when it encounters NULLs. How do I essentially prevent the CONVERT from happening when it encounters a NULL? My core query is as follows:
SELECT
col1
FROM table_a
WHERE
CONVERT(date, col2, 101) > CONVERT(date, col3, 101)
I tried an inner query with an IN clause (i.e., the inner query returns only non-NULL records), but this failed because it seems that the query optimizer runs both queries independently, i.e., it runs the CONVERT on all records, which causes the failure. I also tried a self join (i.e., return only records in the first instance of the table where the records aren't null in the second instance of the table). But, this failed as well because of the same problem in the inner query scenario.
Try this:
SELECT
col1
FROM table_a
WHERE
case
when col2 is null or col3 is null then 0
when CONVERT(date, col2, 101) > CONVERT(date, col3, 101) then 1
end = 1
This method prevents the null strings from being converted (or attempted to be) and lets you decide what else you might want to do if one or the other cols is null.
EDITS: first version contained syntax errors in the case statement - these should be fixed now. Apologies for the hasty typing and not SQLFiddling it.
Try this: (Sample Data Included)
DECLARE #TABLE TABLE
(
SomeText VARCHAR(50),
Date01 VARCHAR(50),
Date02 VARCHAR(50)
)
INSERT INTO #TABLE VALUES('Good Date 01','10/01/2014','12/30/2014')
INSERT INTO #TABLE VALUES('Early Date 01','10/01/2014','12/30/2013')
INSERT INTO #TABLE VALUES('Good Date 02','10/01/2013','10/01/2014')
INSERT INTO #TABLE VALUES('Bad Data 01',NULL,'12/30/2014')
INSERT INTO #TABLE VALUES('Bad Data 02','10/01/2014',NULL)
INSERT INTO #TABLE VALUES('Bad Data 03',NULL,NULL)
SELECT
SomeText,
DATEDIFF(D,CONVERT (DATE, Date01, 101) , CONVERT (DATE, Date02, 101)) AS DELTA
FROM
#TABLE
WHERE
1 = 1
AND ISDATE(Date01) = 1
AND ISDATE(Date02) = 1
and DATEDIFF(D,CONVERT (DATE, Date01, 101) , CONVERT (DATE, Date02, 101)) < 0
The ISDATE(Date01) and ISDATE(Date02) remove missing data points from being attempted by the convert function.
Try
SELECT * FROM #Tmp
WHERE
col2 IS NULL OR col3 IS NULL OR
CONVERT(DATETIME, col2, 101) > CONVERT(DATETIME, col3, 101)
I have tried below query in SQL 2005 its working fine without any error, but it returns all the records without null. Above query return null record too
SELECT * FROM #Tmp WHERE CONVERT(DATETIME, col2, 101) > CONVERT(DATETIME, col3, 101)

How to compare datetime in SQL Server in where clause

I have CreatedDate as datetime column in my database table. I want to fetch the rows where CreatedDate and current time difference is more than 1 hour
Select * from TableName where (DateDiff(hh,CreatedDate,GetDate())>1
Answer by #Amit Singh works if you only care about the hour value itself, versus any 60 minute period.
The problem with using DATEDIFF(hh) that way is that times of 13:01 and 14:59 are only one "hour" apart.
Like:
select datediff(hh,'1/1/2001 13:59','1/1/2001 14:01')
I think doing this would address that issue:
declare #cd datetime='9/12/2013 03:10';
declare #t table(id int,CreatedDate datetime);
insert #t select 1,'9/12/2013 02:50';
insert #t select 2,'9/12/2013 02:05';
select * from #t where #cd>(DateAdd(hh,1,CreatedDate))
Dan Bellandi raises a valid point, but if it really matters if the dates should be 60 minutes apart, then just check if they are 60 minutes apart:
SELECT * FROM TableName WHERE DATEDIFF(MINUTE, DateColumnName, GETDATE()) >= 60
If you don't expect any rows created in the future...
where CreatedDate < dateadd(hour, -1, getdate())
CREATE TABLE trialforDate
(
id INT NULL,
NAME VARCHAR(20) NULL,
addeddate DATETIME NULL
)
INSERT INTO trialforDate VALUES (1,'xxxx',GETDATE())
INSERT INTO trialforDate VALUES (2,'yyyy',GETDATE())
INSERT INTO trialforDate VALUES (1,'zzzz','2013-09-12 11:20:40.533')
SELECT *
FROM trialforDate
WHERE GETDATE() > DATEADD(HOUR, 1, addeddate)
C# Code
DateTime param1= System.DateTime.Now;
DateTime param2= System.DateTime.Now.AddHours(1);
SQL Query:
SELECT * FROM TableName WHERE CreatedDate = param1 AND CreatedDate =param2;

sql server data insertion, first row closing balance should be next row opening balance

I am facing the problem while inserting data this way.
How to insert data this way using stored procedure.
INSERT INTO [dbo].tbl_Transaction
(
[FK_GameID] ,
[SpotID] ,
TransactionReason ,
TransactionType ,
TransactionAmount
--PrevAmountBalance,
-- CurrentBalance
)
SELECT tblTransaction.Row.value('#FK_GameID','BIGINT'),
tblTransaction.Row.value('#SpotID','SMALLINT'),
tblTransaction.Row.value('#TransactionReason','SMALLINT'),
tblTransaction.Row.value('#TransactionType','Varchar(50)'),
tblTransaction.Row.value('#TransactionAmount','MONEY')
--#OpeningBalance,
-- (#OpeningBalance-tblTransaction.Row.value('#TransactionAmount','MONEY'))
FROM #TransactionTable.nodes('/row') AS tblTransaction(Row)
create table #balances(
id int not null identity(1,1),
opening_balance int,
closing_balance int,
t_type varchar(50))
to start the table (if you don't have this you will have to deal with NULLs)
insert into #balances values (100 , 100 , 'start')
query:
insert into #balances values(
(select top 1 closing_balance from #balances order by id desc),
300, --new value
'credit')

T-SQL query with date range

I have a fairly weird 'bug' with a simple query, and I vaguely remember reading the reason for it somewhere a long time ago but would love someone to refresh my memory.
The table is a basic ID, Datetime table.
The query is:
select ID, Datetime from Table where Datetime <= '2010-03-31 23:59:59'
The problem is that the query results include results where the Datetime is '2010-04-01 00:00:00'. The next day. Which it shouldn't.
Anyone?
Cheers
Moo
Take a look at How Are Dates Stored In SQL Server? and How Does Between Work With Dates In SQL Server?
If that is a smalldatetime it has 1 minute precision so if rounds up, for datetime it is 300 miliseconds
example
DECLARE #d DATETIME
SELECT #d = '2001-12-31 23:59:59.999'
SELECT #d
2002-01-01 00:00:00.000
DECLARE #d DATETIME
SELECT #d = '2001-12-31 23:59:59.998'
SELECT #d
2001-12-31 23:59:59.997
Always use less than next day at midnight, in your case
< '20100401'
try doing it like:
select ID, Datetime from Table where Datetime < '2010-04-01'
I always floor the datetime and increment the day and just use "<" less than.
to floor a datetime to just the day use:
SELECT DATEADD(day,DATEDIFF(day,0, GETDATE() ),0)
you can easily increment a datetime by using addition:
SELECT GETDATE()+1
by using the '23:59:59' you can miss rows, try it out:
DECLARE #YourTable table (RowID int, DateOf datetime)
INSERT INTO #YourTable VALUES (1,'2010-03-31 10:00')
INSERT INTO #YourTable VALUES (2,'2010-03-31')
INSERT INTO #YourTable VALUES (3,'2010-03-31 23:59:59')
INSERT INTO #YourTable VALUES (4,'2010-03-31 23:59:59.887')
INSERT INTO #YourTable VALUES (5,'2010-04-01')
INSERT INTO #YourTable VALUES (6,'2010-04-01 10:00')
select * from #YourTable where DateOf <= '2010-03-31 23:59:59'
OUTPUT
RowID DateOf
----------- -----------------------
1 2010-03-31 10:00:00.000
2 2010-03-31 00:00:00.000
3 2010-03-31 23:59:59.000
(3 row(s) affected
this query is wrong, because it does not find the missed rowID=4 record.
if you try to fix this with:
select * from #YourTable where DateOf <= '2010-03-31 23:59:59.999'
then RowID=5 will be included as well, which is wrong.
It's very odd that you are seeing that; I don't know why. But I will suggest that you write the query this way instead:
select ID, Datetime from Table where Datetime < '2010-04-01'

Resources