SQL Server, horizontal concatenate Range of Dates - sql

I would like to know the way I could concatenate between two dates in a calculated column horizontally, for example:
date_ini,date_end,result
2016-04-01,2016-04-05,2016-04-01|2016-04-02|2016-04-03|2016-04-04|2016-04-05
2016-04-03,2016-04-06,2016-04-03|2016-04-04|2016-04-05|2016-04-06
2016-04-05,2016-04-05,2016-04-05
2016-04-05,2016-04-06,2016-04-05|2016-04-06
The result is the column I would like to create
Thanks,

A function like this could do the trick. Please change the size of the return varchar to fit your needs.
CREATE FUNCTION dbo.date_concatenate(#start_date DATETIME, #end_date DATETIME)
RETURNS VARCHAR(255)
AS
BEGIN
DECLARE #result VARCHAR(255);
SET #result = '';
IF(#end_date < #start_date)
SET #result = 'Error: End Date can not be less than start date';
ELSE
BEGIN
WHILE (#start_date < #end_date)
BEGIN
SET #result = #result + CONVERT(varchar(10),#start_date,120) + '|'
SET #start_date = DATEADD(dd,1,#start_date)
END
END
SET #result = #result + CONVERT(varchar(10),#end_date,120)
RETURN #result
END

Related

Cursorfetch :The number of variables must match that of selected columns

I have checked over this several times. The column count matches but it still getting an error belows :
Cursorfetch: The number of variables declared in the INTO list must
match that of selected columns.
I know this question has been asked many times, but I still get stuck. Any help will be appreciated. Thanks.
DECLARE #prev_s_Case CHAR(4)= null,#prev_startDate DATETIME= null,#prev_endDate DATETIME= null, #prev_ukey INT= null, #cur_s_Case CHAR(4), #cur_startDate DATETIME, #cur_endDate DATETIME, #cur_ukey INT, #result varchar(500);
DECLARE THE_CURSOR CURSOR FOR
SELECT s_Case, startDate, endDate, ukey FROM #TEMP
ORDER BY s_Case
BEGIN
OPEN THE_CURSOR;
FETCH NEXT FROM THE_CURSOR
INTO #cur_s_Case, #cur_startDate, #cur_endDate, #cur_ukey
WHILE (##FETCH_STATUS=0)
SELECT s_Case, startDate, endDate, ukey
FROM #TEMP
IF ( (#prev_s_Case = #cur_s_Case))
BEGIN
IF ((#cur_startDate BETWEEN #prev_startDate AND #prev_endDate) AND (#cur_endDate >= #prev_endDate))
BEGIN
SET #result = CASE WHEN #result = '' THEN str(#prev_ukey)
ELSE #result + ','+ str(#prev_ukey) END
END
ELSE IF ((#cur_startDate BETWEEN #prev_startDate AND #prev_endDate)
AND (#cur_endDate < #prev_endDate))
BEGIN
SET #result = CASE WHEN #result = '' THEN str(#cur_ukey)
ELSE #result + ','+ str(#cur_ukey) END
END
END
SET #prev_s_Case= #cur_s_Case;
SET #prev_startDate = #cur_startDate;
SET #prev_endDate = #cur_endDate;
SET #prev_ukey = #cur_ukey;
FETCH NEXT FROM THE_CURSOR
INTO #cur_s_Case,#cur_startDate,#cur_endDate,#cur_ukey
print #result
CLOSE THE_CURSOR;
DEALLOCATE THE_CURSOR;
END

Extract largest number from a string in T-SQL

I am importing working with data imported from excel files. There is a column with a string that can contain multiple numbers. I am trying to extract the largest number in the string or a 0 if there is no string.
The strings are in formats similar to:
"100% post-consumer recycled paper, 50% post-consumer recycled cover, 90% post-consumer recycled wire."
"Paper contains 30% post-consumer content."
or sometimes a empty string or null.
Given the irregular formatting of the string I am having trouble and any help would be appreciated.
Here's a scalar function that will take a string as an input and return the largest whole number it finds (up to a maximum of 3 digits, but from your question I've assumed you're dealing with percentages. If you need more digits, repeat the IF statements ad infinitum).
Paste this into SSMS and run it to create the function. To call it, do something like:
SELECT dbo.GetLargestNumberFromString(MyStringField) as [Largest Number in String]
FROM MyMessedUpData
Function:
CREATE FUNCTION GetLargestNumberFromString
(
#s varchar(max)
)
RETURNS int
AS
BEGIN
DECLARE #LargestNumber int, #i int
SET #i = 1
SET #LargestNumber = 0
WHILE #i <= LEN(#s)
BEGIN
IF SUBSTRING(#s, #i, 3) like '[0-9][0-9][0-9]'
BEGIN
IF CAST(SUBSTRING(#s, #i,3) as int) > #LargestNumber OR #LargestNumber IS NULL
SET #LargestNumber = CAST(SUBSTRING(#s, #i,3) as int);
END
IF SUBSTRING(#s, #i, 2) like '[0-9][0-9]'
BEGIN
IF CAST(SUBSTRING(#s, #i,2) as int) > #LargestNumber OR #LargestNumber IS NULL
SET #LargestNumber = CAST(SUBSTRING(#s, #i,2) as int);
END
IF SUBSTRING(#s, #i, 1) like '[0-9]' OR #LargestNumber IS NULL
BEGIN
IF CAST(SUBSTRING(#s, #i,1) as int) > #LargestNumber
SET #LargestNumber = CAST(SUBSTRING(#s, #i,1) as int);
END
SET #i = #i + 1
CONTINUE
END
RETURN #LargestNumber
END
Pull the data into SQL as-is
Write a query to get a distinct list of options in that column
Add a new column to store the desired value
Write an update statement to populate the new column
As far as determining the largest size, I think you need to look at your data set first, but the update could be as simple as:
DECLARE #COUNTER INT=1000
While EXISTS (SELECT * FROM <Table> WHERE NewColumn is NULL) AND #COUNTER>=0
BEGIN
UPDATE <Table> SET NewColumn=#COUNTER WHERE <SearchColumn> LIKE '%' + CONVERT(VARCHAR,#COUNTER) + '%' AND NewColumn is NULL
SET #COUNTER=#COUNTER-1
END
SQL Fiddle Demo
Generate the LEN(txt) possible RIGHT() fragments of txt. Trim each fragment at the first non-digit character. Test if the remainder is an int. Return the MAX().
SELECT
txt
,MAX(TRY_CONVERT(int,LEFT(RIGHT(txt,i),PATINDEX('%[^0-9]%',RIGHT(txt,i)+' ')-1)))
FROM MyTable
CROSS APPLY (
SELECT TOP(LEN(txt)) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) i FROM master.dbo.spt_values a, master.dbo.spt_values b
) x
GROUP BY txt
I ended up creating a function that handled it. Here is the code:
CREATE FUNCTION [dbo].[cal_GetMaxPercentFromString]
RETURNS float
AS
BEGIN
declare #Numbers Table(number float)
insert into #Numbers
Select 0
declare #temp as varchar(2000) = #string
declare #position int, #length int, #offset int
WHILE CHARINDEX('%', #temp) > 0
BEGIN
set #position = CHARINDEX('%', #temp)
set #offset = 1
set #length = -1
WHILE #position - #offset > 0 and #length < 0
BEGIN
if SUBSTRING(#temp, #position - #offset, 1) not LIKE '[0-9]'
set #length = #offset - 1
set #offset = #offset + 1
END
if #length > 0
BEGIN
insert into #Numbers
select CAST(SUBSTRING(#temp, #position - #length, #length) as float)
END
set #temp = SUBSTRING(#temp, 1, #position - 1) + SUBSTRING(#temp, #position + 1, LEN(#temp) - #position)
END
declare #return as float
select #return = MAX(number) from #Numbers
return #return
END

Why does this TSql return a blank or null value?

Why does the #result value in the code below print out a blank string? I would expect it to concatenate with the previous result.
DECLARE #size int
DECLARE #string nvarchar(10)
DECLARE #result nvarchar(10)
SELECT #string = '12345abc123'
DECLARE #count int, #total int
SELECT
#total = LEN(#string),
#count = 1
WHILE #count <= #total
BEGIN
SELECT #result = SUBSTRING(#string, #count, 1) + '-'+ #result
SELECT #count = #count + 1
PRINT #result
END
You never initialized #result, so it defaults to an sql null. SQL nulls are contagious poison, so when you do
SELECT #result = .... + #result
You're actually doing
SELECT #result = ... + null
and #result simply remains null
Initializing the value to an empty string solves your problem:
SET #result = ''
It is returning a blank because you are concatenating the substring with #result, which initially is NULL.
Try setting #result to an empty string like this this:
SELECT #string = '12345abc123', #result = ''
you have to initialize #result variable
Declare it like this
DECLARE #result nvarchar(10) = ''
this should work

How to toggle case of Entire string in sql

I want to toggle case of entire string.
I am able to do for characters, not for string.
DECLARE #Char AS VARCHAR(1)
SET #Char='a'
IF ASCII(#Char)>=97 AND ASCII(#Char) <=122
PRINT UPPER(#Char)
IF ASCII(#Char)>=65 AND ASCII(#Char) <=90
PRINT LOWER(#Char)
How, I can change case for entire string?
For Ex. "AbCdE", I want to change it to "aBcDe".
You can do it by creating functions:
First make function for one character:
CREATE FUNCTION ToggleChar
(
#Char VARCHAR(1)
)
RETURNS VARCHAR(1)
AS
BEGIN
RETURN CHAR(ASCII(UPPER(#Char))+ASCII(LOWER(#Char))-ASCII(#Char))
END
Then, create function for string:
CREATE FUNCTION ToggleCase
(
#Str VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #ResultStr VARCHAR(MAX)
SET #ResultStr=''
WHILE ( #Str<>'')
BEGIN
SET #ResultStr=#ResultStr + [dbo].[ToggleChar](#Str)
SET #Str= SUBSTRING(#Str,2,LEN(#Str))
END
RETURN #ResultStr
END
Now, use this function to toggle string.
SELECT dbo.ToggleCase('AbCdE') AS ToggleString
Try this:
DECLARE #Name VARCHAR(10) = 'SaMplE'
DECLARE #Count INT = 1
WHILE #Count <= LEN(#Name)
BEGIN
SET #Name = STUFF(#Name, #Count, 1,
CASE
WHEN ASCII(SUBSTRING(#Name,#Count,1)) BETWEEN 97 AND 122 THEN
UPPER(SUBSTRING(#Name,#Count,1))
WHEN ASCII(SUBSTRING(#Name,#Count,1)) BETWEEN 65 AND 90 THEN
LOWER(SUBSTRING(#Name,#Count,1))
END)
SET #Count = #Count + 1
END
SELECT #Name

Eliminate Null Query results from a user defined function

I have the following user defined function that runs correctly; however, it shows all records that return 0 when checked against the ISDATE condition. These records are displayed as NULL values in the query results. I don't want to see those records. How can I remove them from the query results?
I had to setup the ISDATE() check because some log entries have the following format:
("Due Date: -> xx/xx/xxxx" instead of "Due Date: xx/xx/xxxx -> yy/yy/yyyy")
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION ParseValueFromChgLog
(
#LogText varchar(max),
#ValueNum int -- 1 = original date or 2 = changed to date
)
RETURNS date
AS
BEGIN
-- Declare the return variable here
DECLARE #Result date
DECLARE #ValueCheck char(1)
DECLARE #Index bigint
DECLARE #OrigStep bigint
DECLARE #StrDate varchar(max)
-- Parse "Original Date"
IF #ValueNum = 1
BEGIN
SET #Index = 10
SET #OrigStep = 8
SET #StrDate = SUBSTRING(#LogText,CHARINDEX('Due Date', #LogText)+ #Index, #OrigStep)
IF ISDATE(#StrDate) = 1
BEGIN
SET #Result = CAST(SUBSTRING(#LogText,CHARINDEX('Due Date', #LogText)+ #Index, #OrigStep)AS DATE)
--SET #Result = #Date
END
END
-- Parse "Changed to Date"
IF #ValueNum = 2
BEGIN
SET #Index = 21
SET #OrigStep = 9
SET #StrDate = SUBSTRING(#LogText,CHARINDEX('Due Date', #LogText)+ #Index, #OrigStep)
IF ISDATE(#StrDate) = 1
BEGIN
SET #Result = CAST(SUBSTRING(#LogText,CHARINDEX('Due Date', #LogText)+ #Index, #OrigStep)AS DATE)
--SET #Result = #Date
END
END
-- Return the result of the function
RETURN #Result
END
GO
Thanks
There is no way out of returning a value by this function.
But you can filter your query by Where function_Column is not null