How do i split string into 4 columns in ms sql? - sql-server

Example string: " s:6:"module";s:11:"leadCapture"; "
--Note: s is not important.
I tried using string_split:
SELECT value
into temp
FROM STRING_SPLIT('s:6:"module";s:11:"leadCapture";s:6:"action";s:5:"save2";', ';');
select * from temp;
Below is the output:
Row 1: s:6:"module"
Row 2: s:11:"leadCapture"
Row 3: s:6:"action"
Row 4: s:5:"save2"
Expected Output:
6 - column 1,
module - column 2,
11 - column 3,
leadcapture - column 4.

The following code will work starting with MS SQL Server 2016:
declare #s nvarchar(max) = N's:6:"module";s:11:"leadCapture";s:6:"action";s:5:"save2";';
select row_number() over(order by r.Ordinal, v.[key]) as [RN],
v.value as [SubStringValue]
from (
select t.[key] as [Ordinal], t.value as [Value]
from openjson('["' + replace(string_escape(#s, 'json'), ';', '","') + '"]', '$') t
where t.[key] <= 1
) r
cross apply openjson('["' + replace(string_escape(r.Value, 'json'), ':', '","') + '"]', '$') v
where v.[key] > 0
order by RN;
Ugly and convoluted, but at the time of writing this is your only option if you want to do it in pure SQL in an on-prem instance. The alternatives are:
Azure SQL (both SQL Database and Managed Instance) have an improved version of the string_split() function, which accepts an additional parameter, enable_ordinal. This will add an extra column into its output containing ordinal position of substrings within a string. If you use Azure version of SQL, or somehow have SQL Server 2022, this will allow you to avoid having to deal with JSON.
CLR function. Pretty much the best solution when it comes to string manipulation in SQL Server, but can be a pain to maintain.
Cleansing by some ETL tool (SSIS, ADF, AirFlow, whatever) before the data enters the database.

Related

How to use an evaluated expression in SQL IN clause

I have an application that takes a comma separated string for multiple IDs to be used in the 'IN' clause of a SQL query.
SELECT * FROM TABLE WHERE [TABLENAME].[COLUMNNAME]
IN
((SELECT '''' + REPLACE('PARAM(0, Enter ID/IDS. Separate multiple ids by
comma., String)', char(44), ''',''') + ''''))
I have tested that PARAM gets the string entered e.g. 'ID1, ID2' but SELECT/REPLACE does not execute. The statement becomes,
SELECT * FROM TABLE WHERE [TABLENAME].[COLUMNNAME]
IN
((SELECT '''' + REPLACE('ID1,ID2', char(44), ''',''') + ''''))
I am trying to achieve,
SELECT * FROM TABLE WHERE [TABLENAME].[COLUMNNAME]
IN ('ID1', 'ID2')
The query does not return any results/errors. I am confident the corresponding records are in the database I am working with. Not sure how to fix this.
You can't do it like this. The IN operator expects a list of parameters separated by comma, but you supply it with a single parameter that happens to contain a comma delimited string:
If you are working on SQL Server version 2016 or higher, you can use the built in string_split to convert the delimited string into a table.
SELECT *
FROM TABLE
WHERE [TABLENAME].[COLUMNNAME]
IN STRING_SPLIT(#CommaDelimitedString, ',')
For older versions, there are multiple user defined functions you can choose from, my personal favorite is Jeff Moden's DelimitedSplit8K. For more options, read Aaron Bertrand's Split strings the right way – or the next best way.

Get minimum value from columnconcat from three tables + lpad inside. MS SQL

I am working in SQL Server Managment Studio 2014.
In the project I am working on I have three tables, each containing 2 columns, one datetime with the exact date (but on time is contained) and the other one - smallint containing time (8:55 is 855 value, while for example 14:45 is 1445).
What I want to do is to get minimum value which is merged from both of those columns from all of those three tables.
What I have figure out by myself until now is:
Use lpad("U_StartTime", 0, '4') to fill values like 855 into 0855 (for exact comparison). However lpad is not recognized at my studio.
lpad is not recognized built in function
Then I can merge both columns like this:
SELECT concat("U_StartDate", ' ', "U_StartTime") FROM "TABLE1".
This is ok until I try make it with lpad.
Then I may take all values to consider like this:
SELECT concat("U_StartDate", ' ', "U_StartTime") FROM "TABLE1"
UNION
SELECT concat("U_StartDate", ' ', "U_StartTime") FROM "TABLE2"
...
And I can take MIN(column) but I do not know how to get MIN from the whole UNION SELECT (of those three tables).
Thank you in advance for any advices on my current sql problems.
edit - image for NikHil:
EDIT:
I have changed the way a bit. Now I am modifying datetime object rather than working on string comparison. As an example for someone I paste part of the code:
select DATEADD(minute, "U_StartTime"%100, DATEADD(hour, "U_StartTime"/100, "U_StartDate")) from "TABLE1"
rather than
select MIN(concat("U_StartDate", ' ', RIGHT('0000' + "U_StartTime", '4'))) from "TABLE1"
You can use RIGHT instead of lpad
SELECT RIGHT('0000' + '855', 4) -- 0855
SELECT RIGHT('0000' + '1445', 4) -- 1445
Query looks like
SELECT MIN(RIGHT('0000' + YourColumn, 4) * 1)
FROM
Tbl
may be you can try this
select data from
(
select concat("U_StartDate", ' ', "U_StartTime")as 'data' from "TABLE1"
UNION
select concat("U_StartDate", ' ', "U_StartTime")as 'data' from "TABLE2"
...
)
where data is not null
order by data asc
LIMIT 1;

Need Help Converting Oracle Query to SQL Server

Several weeks ago I made a post to get help with converting a comma delimited list of values into a format that it could be used as part of an IN clause in Oracle. Here is a link to the post.
Oracle invalid number in clause
The answer was to split up the list into an individual row for each value. Here's the answer that I ended up using.
SELECT trim(regexp_substr(str, '[^,]+', 1, LEVEL)) str
FROM ( SELECT '1,2,3,4' str FROM dual )
CONNECT BY instr(str, ',', 1, LEVEL - 1) > 0
Is there a way that I can do something similar in SQL Server without having to create a custom function? I noticed that there's a STRING_SPLIT function, but I don't seem to have access to that on this SQL Server.
Any advice you might have would be greatly appreciated. I've been trying to take a stab at this for the majority of the day.
String_split function is available in MS SQL Server starting from version 2016. If you use older version you can write a few lines of code which do the same.
declare #str varchar(100)='1,2,3,4' --initial string
;with cte as (--build xml from the string
select cast('<s>'+replace(#str,',','</s><s>')+'</s>' as xml) x
)
--receive rows
select t.v.value('.[1]','int') value
from cte cross apply cte.x.nodes('s') t(v)

How to produce JSON strings from SQL Server queries via TSQL?

I wanted to know if there is any function or something to convert the SQL select query result to JSON string format?
For example, SQL select query result is,
current target
-----------------
500 1000
1500 2000
JSON result:
[{"current":500,"target":1000},{"current":1500,"target":2000}]
Any ideas will be helpful.
Thanks.
SQL Fiddle
MS SQL Server 2008 Schema Setup:
Query 1:
DECLARE #TABLE TABLE ([current] INT, [target] INT)
INSERT INTO #TABLE VALUES
(500 , 1000),
(1500 , 2000)
SELECT '[' + STUFF((SELECT ',{"current":' + CAST([current] AS VARCHAR(30))
+ ',"target":' + CAST([target] AS VARCHAR(30)) + '}'
FROM #TABLE
FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'),1,1,'') + ']'
Results:
[{"current":500,"target":1000},{"current":1500,"target":2000}]
You don't specify version.
In SQL Server 2016 you will be able to do something like
SELECT [current],
target
FROM YourTable
ORDER BY [current]
FOR JSON AUTO;
More details here or in the official pre release documentation
I use
SELECT
JSON_QUERY(( SELECT
[current],target
FROM YourTable
FOR JSON PATH
))
Works well with minimal effort. I generally convert the output to a List<Dictionary<string,dynamic>> in C#/.Net (if I don't have an existing model).

Generate SQL insert statements of some records in a table

I try to auto generate insert SQL statement from an existing table in SQLServer 2008 but I do not need all record, only a small part of them. --> I thus need to filter the generated inserts. Adding a WHERE clause when generating the insert SQL statements would do the trick but I do not know how to do it.
This article answer to my question partly (SSMS internal generator) :
What is the best way to auto-generate INSERT statements for a SQL Server table?
But it exports all the data of a table. The insert scripts generated are not sorted thus I cannot filter the row I need easily (heavy manual work).
I also tried this stored procedure here (I also had to correct a part of the procedure to make it work with SQLServer 2008 replace char(255) by varchar as explained here)
But it is still not working : I get the following error :
Msg 8169, Level 16, State 2, Line 6
Conversion failed when converting from a character string to uniqueidentifier.
Could you then give me the best way to auto generate SQL Insert in SQL server 2008 from a part of a portion of a table (thus not all the rows of the table) ?
I found a way myself using Excel.
Make needed query including WHERE clause in SSMS
Select all the result
Copy with header
Paste in Excel file here under in 4th row, 1st column
Change in macro output path
Change in cell table name
Launch macro
--> take the file generated and you have a copy of your data ready to be insert again
https://dl.dropboxusercontent.com/u/49776541/GenerateInsert.xlsm
You can use merge syntax to insert data in table based on specific condition
using merge you can also delete and update data in table.you can also do
multiple operation in single sql statement.
There is an easier way to do this, other than going through all the fuss of an excel sheet.
This will return all the data in a table (much like the GUI version) where you right click on the database and select “Tasks” then select “Generate scripts”.
However, unlike the GUI version or the “export to excel” version, with this line of code, you can specify a filter in a “WHERE” clause to return only items for a particular day, or range of days, or any other filter that would normally be used in a “WHERE” clause.
In the code below, I am using 2 simple tables. One is populated with data, the other is not. I want to transfer some or all of the data from table2 to table3. Again, I can filter by date or parts of other columns. (for example… WHERE colB LIKE 'ging%';
This will generate a string of “INSERT” statements preformed in SQL query ready to run.
Note, before running this, switch your output display in SQL server from “Grid” to “Text”.
SELECT 'INSERT', + 'INTO', + 'TestTable3', + '(', + 'colA', + ',', + 'colB', + ',', + 'colDate', + ')', + 'values', + '(', + '''', + CAST(colA AS VARCHAR(10)), + '''', + ',', + '''', + CAST(colB AS VARCHAR(10)), + '''', + ',', + '''', + CAST(DATEADD(DAY, -1, GETDATE()) AS DATE) AS 'colDate', + '''', + ')', + ';'
FROM TestTable2
WHERE colDate LIKE '2018-10-14';
GO
Here is a snippet of what this will return.
Simply copy/paste the results into a new query and run it.
Too easy.

Resources