sql code to convert varchar colum to int - sql

I am stuck on converting a varchar column schedule containing the following data 0, 1, 2, 3,4,8,9,10,11,12,15,16,17,18,19 to INT. I know, please don't ask why this schedule column was not created as INT initially, long story.
So I tried this, but it doesn't work. and give me an error:
select CAST(schedule AS int) from shift_test:
the query should check if the numbers representing days are found in the schedule filed using the sql code below
select empid, case when ((DateDiff(hour,'01-01-2014 07:00' , '01-01-2014 00:00')/ 24 )% 15) in ( CAST(schedule AS int))
then 'A' else '*' end as shift_A from Shift_test
After executing i get this error.
Conversion failed when converting the varchar value to int.
Any help will be appriciated

Use ISNUMERIC() test if you are using version 2008 or 2008R2. In SQL SERVER 2012 you can use TRY_CAST() function, which checks if the data conversion is allowed for given literal.
Mock up code for SQL Server 2008/R2:
Select col1, col2,
case
when <condition> and isnumeric(col2) then cast(col2 as int)
else <do whatever...>
end
as converted_col2
from <yourtable>;
For SQL Server 2012:
Select col1, col2,
case
when <condition> then try_cast(col2 as int)
else <do whatever...>
end
as converted_col2
from <yourtable>;
Example with SQl Server 2008
declare #T table (empid int, schedule varchar(2)) ;
insert into #T(empid, schedule) values (1, '1');
insert into #T(empid, schedule) values (2, '2');
insert into #T(empid, schedule) values (3, '03');
insert into #T(empid, schedule) values (4, '4');
insert into #T(empid, schedule) values (5, '05');
insert into #T(empid, schedule) values (6, 'A');
select empid,
case
when ISNUMERIC(schedule) = 1
and ((DateDiff(hour,'01-01-2014 07:00' , '10-01-2014 00:00')/ 24 )% 15)
in ( CAST(schedule AS int)) then 'A'
else '*'
end
as shift_A
from #T;

# Binaya Ive added my code for more help.
The schedule column contain (0, 1, 2, 3,4,8,9,10,11,12,15,16,17,18,19) which is varchar.
i want to output A if after this calculation ((DateDiff(hour,'01-01-2014 07:00',startdate)/ 24 )% 15) the result is found in the schedule column else if after the calculation and the result is not found output *
;with Shift_runover (shift_code,schedule,endd,startdate)
-- Start at the beginning of shift.
as
(select shift_code,schedule,Cast(end_date as DateTime) as endd,Cast(start_date as DateTime)as startdate from dbo.Shift_test
union all
-- Add hours up to the desired end date.
select shift_code,schedule,endd,DateAdd(hour, 1,startdate)from Shift_runover where startdate<=endd),
Extendedsamples as
(
-- Calculate the number of days since the beginning of the first shift on 1/1/2014.
select shift_code,schedule,startdate,DateDiff(hour,'01-01-2014 07:00',startdate)/ 24 as Days from Shift_runover ),
Shifts as
(
-- the schedule column contain (0, 1, 2, 3,4,8,9,10,11,12,15,16,17,18,19) which is varchar.
-- i want to output A if ((DateDiff(hour,'01-01-2014 07:00',startdate)/ 24 )% 15) is found in the schedule colume
select *,
case when (DateDiff(hour,'01-01-2014 07:00',startdate)/ 24 )% 15 in(schedule)
then 'A' else '*' end as shift_A
from ExtendedSamples
)
select *
from Shifts
option ( maxrecursion 0 )

Related

How can I delete trailing contiguous records in a partition with a particular value?

I'm using the latest version of SQL Server and have the following problem. Given the table below, the requirement, quite simply, is to delete "trailing" records in each _category partition that have _value = 0. Trailing in this context means, when the records are placed in _date order, any series or contiguous block of records with _value = 0 at the end of the list should be deleted. Records with _value = 0 that have subsequent records in the partition with some non-zero value should stay.
create table #x (_id int identity, _category int, _date date, _value int)
insert into #x values (1, '2022-10-01', 12)
insert into #x values (1, '2022-10-03', 0)
insert into #x values (1, '2022-10-04', 10)
insert into #x values (1, '2022-10-06', 11)
insert into #x values (1, '2022-10-07', 10)
insert into #x values (2, '2022-10-01', 1)
insert into #x values (2, '2022-10-02', 0)
insert into #x values (2, '2022-10-05', 19)
insert into #x values (2, '2022-10-10', 18)
insert into #x values (2, '2022-10-12', 0)
insert into #x values (2, '2022-10-13', 0)
insert into #x values (2, '2022-10-15', 0)
insert into #x values (3, '2022-10-02', 10)
insert into #x values (3, '2022-10-03', 0)
insert into #x values (3, '2022-10-05', 0)
insert into #x values (3, '2022-10-06', 12)
insert into #x values (3, '2022-10-08', 0)
I see a few ways to do it. The brute force way is to to run the records through a cursor in date order, and grab the ID of any record where _value = 0 and see if it holds until the category changes. I'm trying to avoid T-SQL though if I can do it in a query.
To that end, I thought I could apply some gaps and islands trickery and do something with window functions. I feel like there might be a way to leverage last_value() for this, but so far I only see it useful in identifying partitions that have the criteria, not so much in helping me get the ID's of the records to delete.
The desired result is the deletion of records 10, 11, 12 and 17.
Appreciate any help.
I'm not sure that your requirement requires a gaps and islands approach. Simple exists logic should work.
SELECT _id, _catrgory, _date, _value
FROM #x x1
WHERE _value <> 0 OR
EXISTS (
SELECT 1
FROM #x x2
WHERE x2._category = x1._category AND
x2._date > x1._date AND
x2._value <> 0
);
Assuming that all _values are greater than or equal to 0 you can use MAX() window function in an updatable CTE:
WITH cte AS (
SELECT *,
MAX(_value) OVER (
PARTITION BY _category
ORDER BY _date
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) max
FROM #x
)
DELETE FROM cte
WHERE max = 0;
If there are negative _values use MAX(ABS(_value)) instead of MAX(_value).
See the demo.
Using common table expressions, you can use:
WITH CTE_NumberedRows AS (
SELECT *, rn = ROW_NUMBER() OVER(PARTITION BY _category ORDER BY _date)
FROM #x
),
CTE_Keepers AS (
SELECT _category, rnLastKeeper = MAX(rn)
FROM CTE_NumberedRows
WHERE _value <> 0
GROUP BY _category
)
DELETE NR
FROM CTE_NumberedRows NR
LEFT JOIN CTE_Keepers K
ON K._category = NR._category
WHERE NR.rn > ISNULL(K.rnLastKeeper, 0)
See this db<>fiddle for a working demo.
EDIT: My original post did not handle the all-zero's edge case. This has been corrected above, together with some naming tweaks. (The original can still be found here.
Tim Biegeleisen's post may be the simpler approach.

Discrepancy in result when calculating time using decimal(10,1)

I have query that returns total seconds as 28943 , I am using below query to convert seconds
CREATE TABLE dbo.MyTable
(
userID int,
uDateTime datetime,
totalsec bigint
)
INSERT INTO dbo.MyTable VALUES (123, getdate(),1503);
INSERT INTO dbo.MyTable VALUES (123, getdate(),893);
INSERT INTO dbo.MyTable VALUES (123, getdate(),14524);
INSERT INTO dbo.MyTable VALUES (123, getdate(),6631);
INSERT INTO dbo.MyTable VALUES (123, getdate(),13);
INSERT INTO dbo.MyTable VALUES (123, getdate(),889);
INSERT INTO dbo.MyTable VALUES (123, getdate(),4490);
GO
SELECT userid,Format( SUM(CAST((CAST(totalsec as float) / 3600)as decimal(10,1))) ,'N1')
FROM dbo.MyTable
group by userid,cast(udatetime as date)
```
Output : 1,'07/07/2021',7.8
When I am running below query
```
SELECT
FORMAT(SUM(CAST((CAST(28943 AS float) / 3600) AS decimal(10, 1))), 'N1')
```
Output : 8.0
I was wondering why there is this discrepancy in output?
The first query get its data from a table were you sum up values that you have cut if with decimal(10,1)
In the secound query you already inserted the sum. The sum function doesn't do anything without a table as source.
Hence you have different results because you calculated with different values.
I found out why I am getting 7.8 .
below query solved the issue
SELECT userid,Format( CAST(SUM(CAST(totalsec as float) / 3600)as decimal(10,1)) ,'N1')
FROM dbo.MyTable
group by userid,cast(udatetime as date)

GetDate() returns constant literal error, how to solve? [duplicate]

Consider this table:
CREATE TABLE t (i int, j int, ...);
I want to insert data into a table from a set of SELECT statements. The simplified version of my query is:
INSERT INTO t VALUES ((SELECT 1), (SELECT 2), ...);
The real query can be much more complex, and the individual subqueries independent. Unfortunately, this standard SQL statement (which works on SQL Server) doesn't work on SQL Data Warehouse. The following error is raised:
Failed to execute query. Error: Insert values statement can contain only constant literal values or variable references.
Is there a way to work around this?
It appears that there are a few limitations on the INSERT .. VALUES statement of SQL Data Warehouse, but none on INSERT .. SELECT. The requested query can be rewritten to:
INSERT INTO t SELECT (SELECT 1), (SELECT 2);
This workaround is also useful when inserting multiple rows:
-- Doesn't work:
INSERT INTO t VALUES ((SELECT 1), 2), ((SELECT 2), 3), ...;
-- Works:
INSERT INTO t SELECT (SELECT 1), 2 UNION ALL SELECT (SELECT 2), 3;
You can also just run a CREATE TABLE AS SELECT (CTAS) statement. This gives you the full syntax support in the SELECT statement and control of the table shape (distribution type, index type) in the statement. A CTAS statement is fully parallalized.
Strange syntax, but it works. Here is a more complex example:
CREATE TABLE [MDM].[Fact_Management_Curve]
(
[Scenario_ID] INT NOT NULL,
[FundingYYYYMM] CHAR(6) NOT NULL,
[CollectionYYYYMM] CHAR(6) NOT NULL,
[CorpID] INT NOT NULL,
[Multipler] FLOAT NOT NULL
)
GO
INSERT INTO [MDM].[Fact_Management_Curve]
SELECT (SELECT 1), 201701, 201701, 21, 0.010170154301011 UNION ALL
SELECT (SELECT 1), 201701, 201702, 21, 0.010170278901234 UNION ALL
SELECT (SELECT 1), 201701, 201703, 21, 0.010170375659900 UNION ALL
SELECT (SELECT 1), 201701, 201704, 21, 0.010170482998344
GO
SELECT * FROM [MDM].[Fact_Management_Curve]
ORDER BY 1,2,3,4;
Scenario_ID FundingYYYYMM CollectionYYYYMM CorpID Multipler
1 201701 201701 21 0.010170154301011
1 201701 201702 21 0.010170278901234
1 201701 201703 21 0.0101703756599
1 201701 201704 21 0.010170482998344
For your information...
INSERT INTO table_name VALUES Syntax only accepts constant literal values or variable references. Anything like Expression is invalid.
For Example INSERT INTO table_name VALUES (A,B,A+B)
But
DECLARE #C INT = A+B
INSERT INTO table_name VALUES (A,B,C) is valid one.
Here A+B is like any kind of expressions so it throw the error like "only accepts constant literal values or variable references"

Insert values statement can contain only constant literal values or variable references in SQL Data Warehouse

Consider this table:
CREATE TABLE t (i int, j int, ...);
I want to insert data into a table from a set of SELECT statements. The simplified version of my query is:
INSERT INTO t VALUES ((SELECT 1), (SELECT 2), ...);
The real query can be much more complex, and the individual subqueries independent. Unfortunately, this standard SQL statement (which works on SQL Server) doesn't work on SQL Data Warehouse. The following error is raised:
Failed to execute query. Error: Insert values statement can contain only constant literal values or variable references.
Is there a way to work around this?
It appears that there are a few limitations on the INSERT .. VALUES statement of SQL Data Warehouse, but none on INSERT .. SELECT. The requested query can be rewritten to:
INSERT INTO t SELECT (SELECT 1), (SELECT 2);
This workaround is also useful when inserting multiple rows:
-- Doesn't work:
INSERT INTO t VALUES ((SELECT 1), 2), ((SELECT 2), 3), ...;
-- Works:
INSERT INTO t SELECT (SELECT 1), 2 UNION ALL SELECT (SELECT 2), 3;
You can also just run a CREATE TABLE AS SELECT (CTAS) statement. This gives you the full syntax support in the SELECT statement and control of the table shape (distribution type, index type) in the statement. A CTAS statement is fully parallalized.
Strange syntax, but it works. Here is a more complex example:
CREATE TABLE [MDM].[Fact_Management_Curve]
(
[Scenario_ID] INT NOT NULL,
[FundingYYYYMM] CHAR(6) NOT NULL,
[CollectionYYYYMM] CHAR(6) NOT NULL,
[CorpID] INT NOT NULL,
[Multipler] FLOAT NOT NULL
)
GO
INSERT INTO [MDM].[Fact_Management_Curve]
SELECT (SELECT 1), 201701, 201701, 21, 0.010170154301011 UNION ALL
SELECT (SELECT 1), 201701, 201702, 21, 0.010170278901234 UNION ALL
SELECT (SELECT 1), 201701, 201703, 21, 0.010170375659900 UNION ALL
SELECT (SELECT 1), 201701, 201704, 21, 0.010170482998344
GO
SELECT * FROM [MDM].[Fact_Management_Curve]
ORDER BY 1,2,3,4;
Scenario_ID FundingYYYYMM CollectionYYYYMM CorpID Multipler
1 201701 201701 21 0.010170154301011
1 201701 201702 21 0.010170278901234
1 201701 201703 21 0.0101703756599
1 201701 201704 21 0.010170482998344
For your information...
INSERT INTO table_name VALUES Syntax only accepts constant literal values or variable references. Anything like Expression is invalid.
For Example INSERT INTO table_name VALUES (A,B,A+B)
But
DECLARE #C INT = A+B
INSERT INTO table_name VALUES (A,B,C) is valid one.
Here A+B is like any kind of expressions so it throw the error like "only accepts constant literal values or variable references"

Sql Query With Select and IF

here is my table description:
Table Name : Orders
Columns : ID, NO, Quantity, Base, Code
First my query should check the value of Code, if value of Code is 'B' then OUTPUT VALUE should be Code+Base if it is not 'B' then OUTPUT VALUE should be Code+Quantity
the obtained rows again will be filtered by using where clause where ID='' and quantity=''
How can I form this complex query, any ideas ?...
Modified Answer
Something bothered me about my original post (see below, but do not use) so I went back to check. If Code is 'B' (therefore a varchar) and Quantity is an integer, then SQL will not let you add them for obvious reasons and will not do an implicit conversion for you (at least it did not do it for me). So I had to convert Quantity to a varchar to be able to use it.
Look at the following working code built on SQL Server 2008
DECLARE #MyTable TABLE
(
ID int identity (1, 1),
Num int,
Quantity int,
Base varchar (1),
Code varchar (1)
)
INSERT INTO #MyTable VALUES
(1, 1, 'a', 'A')
, (2, 2, 'b', 'B')
, (3, 3, 'c', 'C')
, (4, 4, 'd', 'D')
, (5, 5, 'e', 'E')
SELECT * FROM #MyTable
SELECT
CASE WHEN Code = 'B' THEN Code+Base
ELSE Code+CONVERT (VarChar, Quantity)
END AS OutputValue
FROM #MyTable
Original Answer (do not use)
try the following
SELECT CASE WHEN Code = 'B' THEN Code+Base ELSE Code+Quantity END AS OutputValue
FROM MyTable
WHERE ID = #Id
and Quantity = #Quantity
SELECT CASE Code WHEN 'B' THEN Code + Base ELSE Code + Quantity END As OutputValue
FROM Orders
WHERE ID = #id AND Quantity = #quantity
SELECT
(
CASE Code
WHEN CODE = 'B' THEN Code+Base
ELSE Code+Quantity
END
) AS OutputValue
FROM Orders
WHERE ID = '' AND Quantity=''