I am worried about the performance of the following query:
SELECT
MAX(CAST((CONVERT(bigint, DBTimeStamp)) AS decimal)) AS DBTimeStamp
FROM Category
WHERE DepartmentID = 5
Is there a faster way of getting the biggest/latest timestamp as integer from a table?
If you calculate the max befor the converting and casting SQL can use an index and only need to convert and cast once:
SELECT
CAST(CONVERT(bigint,MAX( DBTimeStamp)) AS decimal) AS DBTimeStamp
FROM Category
WHERE DepartmentID = 5
Related
I have a table with columns id(int) and trans_id string.
trans_id contains values such as 20345,19345 - the 1st 2 chars represent years, I want a query for transactions that happened in 2020,2019
You should store dates in a date or datetime column, not as a string or integer. And you certainly shouldn't store multiple values in one column.
Assuming trans_id is an int you can do
SELECT *
FROM YourTable t
WHERE trans_id >= 19000 AND trans_id < 21000;
If trans_id is a varchar string, you can do
SELECT *
FROM YourTable t
WHERE trans_id LIKE '20%' OR trans_id LIKE '19%';
If you've gone for an even worse version and stored multiple values, you need to split them first
SELECT *
FROM YourTable t
WHERE EXISTS (SELECT 1
FROM STRING_SPLIT(trans_id, ',') s
WHERE s.value LIKE '20%' OR s.value LIKE '19%'
);
You can also use LEFT to get the first two characters of the string.
Then use IN for the list of years you need.
SELECT *
FROM YourTable t
WHERE LEFT(trans_id, 2) IN ('19', '20')
But don't use BETWEEN without casting the 2 digits to an INT.
I have a VarChar column in SQL Server in which I am storing mostly numbers but there are also some strings. I wanted to use
Select column1
from table
Order by Column1 Asc
but it sorts the numbers in this order instead
1
10
11
12
19
2
3
4
5
String1
String2
...
I have searched for a way to do this online and the recommended method was to cast as INT or do:
Select column1
from table
Order by Column1 + 0 Asc
However, those solutions does not work for me because I have strings in my column and I get the error:
Conversion failed when converting the varchar value 'Damage' to data type int.
Suppose that you have a table like this:
CREATE TABLE #y(i VARCHAR(10))
and you have inserted the following data in it:
INSERT INTO #y VALUES('1'),('2'),('10'),('9'),('20'),('ffff'),('aaaa'),('zzzz')
You can try the following query to sort the data properly as you need:
SELECT * FROM #y
ORDER BY CASE ISNUMERIC(i) WHEN 1 THEN CAST(i AS INT) ELSE 99999999999 end ASC, i ASC
You can find many other ways to solve this problem here too.
Read more about ISNUMERIC, CAST and CASE
I have a table AgentDetail, and I need to create a query which returns only records which contain left most 5 numeric digits.
The table has 3 columns
AgentId, AgentName, AgentTextCode
where in the AgentTextCode column, there could be 5 digits or any text value (sometime 2 bytes chars). So output records should be only those which have a value which starts with 5 numeric digits (decimal value not possible).
Sample data & output:
We can use LIKE here:
SELECT
AgentID, AgentName, AgentTextCode
FROM yourTable
WHERE AgentTextCode LIKE '[0-9][0-9][0-9][0-9][0-9]%';
SQL Server's LIKE operator supports some primitive regex capabilities, as shown above.
You can use IsNumeric and Substring from TSQL:
SELECT
AgentID, AgentName, AgentTextCode
FROM yourTable
WHERE ISNUMERIC(Replace(Replace(substring(AgentTextCode, 1, 5),'+','A'),'-','A') + '.0e0') = 1;
GO
Reference here:
CAST and IsNumeric
Context: SQL Server 2008
I have a table mytable which contains two NVARCHAR columns id, title.
All data in the id column are in fact numeric, except one row which contains the value 'test'.
I want to get all ids between 10 and 15 so I need SQL Server to convert id column values to INTEGER.
I use ISNUMERIC(id) = 1 to eliminate the non numeric values first but SQL Server is being rather weird with this query.
SELECT
in.*
FROM
(SELECT
id, title
FROM
mytable
WHERE
ISNUMERIC(id) = 1) in
WHERE
in.id BETWEEN 10 AND 15
This query causes the following error:
Conversion failed when converting the nvarchar value 'test' to
data type int.
The inner query eliminates the row with the 'test' id value so 'in' shouldn't contain it. Why is SQL Server still trying to convert it?
Am I missing something? How can I get around this?
P.S. I tried WHERE CAST(in.id AS INTEGER) BETWEEN 10 AND 15 but didn't work either.
Use TRY_CONVERT function, it's very handy.
SELECT id,
title
FROM mytable
where TRY_CONVERT(int, id) is not NULL
and TRY_CONVERT(int, id) BETWEEN 10 and 15
TRY_CONVERT returns null if the conversion fails.
And for you error, I suppose that the Query Optimizer messes something up here. Take a look at the execution plan, maybe it's filtering values between 10 and 15 at the first place. My solution will always work.
As the other commenter said in your case the BETWEEN function is done before ISNUMERIC. Here is a simple example:
select * into #temp2
from (
select 'test' a
union
select cast(1 as varchar) a
union
select cast(2 as varchar) a
union
select cast(3 as varchar) a
)z
SELECT a FROM (
SELECT a FROM #temp2 WHERE ISNUMERIC(a) = 1
) b
WHERE b.a BETWEEN 10 AND 15
This simple query is an alternative:
SELECT a
FROM #temp2
WHERE ISNUMERIC(a) = 1
and a BETWEEN 10 AND 15
I should add one more way with XML style:
SELECT *
FROM mytable
WHERE CAST(id as xml).value('. cast as xs:decimal?','int') BETWEEN 10 AND 15
Convert id to XML, convert the value in xs:decimal and then convert to integer. If there is not numeric value it will be converted into NULL.
Here you can read about XML type casting rules (link).
Could create a new field to do the search on:
Select id, title
from (Select id, title, case id when 'test' then null else cast(id as int) end as trueint from mytable) n
where n.trueint between 10 and 15
OR
Select id, title
from mytable
where case isnumeric(id) when 1 then cast(id as int) else null end between 10 and 15
One possibility is to force the engine to work this in two steps:
DECLARE #tbl TABLE(id NVARCHAR(MAX),title NVARCHAR(MAX));
INSERT INTO #tbl
SELECT id, title FROM mytable WHERE ISNUMERIC(id) = 1;
SELECT t.*
FROM #tbl t
WHERE CAST(t.id AS INT) BETWEEN 10 AND 15
select *
from employee
where DATEPART(MM ,empDOJ) + DATEPART(yy,empDOJ) < 2013 + 5
I want employee detail from table "employee" where date of join of employee is less than may 2013 but above query is not working properly and "empdoj" is date in sql
correct way of doing this would be
select *
from employee
where empDOJ < convert(date, '20130501', 112)
But you can use string '20130501' or '2013-05-01' because when you compare it to date column, SQL Server will convert data types according to data type priorities. Since date type is higher priority than varchar type, SQL will convert varchar to date implicitly:
select *
from employee
where empDOJ < '20130501'
Note that using functions on your column prevent from using indexes on this column, so when you're writing where datepart(MM ,empDOJ) = 5 index (if you have index on empDOJ column) will not be used.
SELECT *
FROM EMPLOYEE
WHERE EMPDOJ < '2013-05-01'