concat two integers and result as string in SQL - sql

In table, 2 fields ID as int and Number as small int and i want to concatenate the two fields and display as string
eg: ID = 101 and Number = 9
output : 101.9
Dot to be added in between ID and Number?
How to query in SQL?

You can CAST your integer field to varchar and then concatenate them as you want.
DECLARE #ID INT
DECLARE #Number INT
SET #ID = 101
SET #Number = 9
SELECT CAST(#ID AS VARCHAR(10) ) +'.'+ CAST(#Number AS VARCHAR(10) )

In SQL 2012 (and later) I now find this easier using CONCAT (better performance too)
SELECT CONCAT(#ID, '.', #Number)
any NULL elements are converted to empty-strings preventing NULL propagation, which saves having to do the even more complex:
SELECT ISNULL(CAST(#ID AS VARCHAR(10) ), '') +'.'+ ISNULL(CAST(#Number AS VARCHAR(10) ) , '')

Related

Get row that had multi string in name SQL server

I'm using SQL server 2014 I try to get row that have multi-value in name like:
declare #value ='m n'
So the value that return should have 'm' and 'n' in any position
I tried to use
Select * from Table where contains(name,N'"*m*" and "*n*"')
But the value return only if it started by 'm' and 'n'
I had also tried:
select * from Table where name like '%m%n%'
the value return only if name contains 'm' then 'n' not 'n' then 'm'.
Note: I'm getting value from parameter so I don't known how many char or what position so I'm using replace on #value to get what I want.
Since you want to use that variable.
Then best split the letters or words.
Having the STRING_SPLIT function would be great for this.
But there are more ways to split strings.
The example below does it with a WHILE loop.
CREATE TABLE [Table]
( id INT IDENTITY(101,1) PRIMARY KEY,
name NVARCHAR(100) NOT NULL
);
GO
✓
INSERT INTO [Table] (name) VALUES
('a munchkin'),
('never ever sever mah lever'),
('saintess'),
('them mammaries');
GO
4 rows affected
DECLARE #value NVARCHAR(1000);
SET #value =' m n ';
DECLARE #values TABLE (
value NVARCHAR(42)
);
DECLARE #words NVARCHAR(1000);
DECLARE #word NVARCHAR(42);
SET #words = RTRIM(LTRIM(#value))+' ';
WHILE CHARINDEX(' ', #words) > 0
BEGIN
SET #word = SUBSTRING(#words,0,CHARINDEX(' ',#words))
SET #words = LTRIM(SUBSTRING(#words,CHARINDEX(' ',#words)+1,LEN(#words)))
IF #word != '' INSERT INTO #values (value) VALUES (#word);
END;
DECLARE #TotalValues INT;
SET #TotalValues = (select count(distinct value) from #values);
--
-- use the table variable to query the table
--
SELECT *
FROM [Table] t
WHERE EXISTS
(
SELECT 1
FROM #values v
WHERE t.name LIKE '%'+v.value+'%'
HAVING COUNT(DISTINCT v.value) = #TotalValues
);
GO
id | name
--: | :-------------------------
101 | a munchkin
102 | never ever sever mah lever
db<>fiddle here
You have to separate your conditions like this
select * from Table where name like '%m%' and name like '%n%'

SQL search in two columns with one combined value

I will try to demonstrate what I am trying to achieve. This is an oversimplified example for my case.
Suppose I have a table contains two columns
ID YEAR
--- ----
1 2017
2 2018
and I have a search term 2017 / 1
What I want to do is something like this
select * from table where 'YEAR / ID' LIKE '%searchterm%'
Is this possible ?
Thanks in advance.
In my opinion the most effective way is:
Firstly divide String x = "2017 / 1" to two int values int year = 2017, int id = 1. I don't know what kind of programing language you are using but all of programing languages have special functions to make it easily (between all values you have '/').
Then use this query:
Select *
from table
where year = 2017
and id = 1
Use Below query, I have considered your search text format as 2017 / 1.
DECLARE #tblTest AS Table
(
Id INT,
YearNo INT
)
INSERT INTO #tblTest values (1,2017)
INSERT INTO #tblTest values (2,2018)
INSERT INTO #tblTest values (3,2017)
INSERT INTO #tblTest values (4,2018)
DECLARE #searchterm VARCHAR(50)='2017 / 1'
LEFT will give you string starting from left position to applied length.
RIGHT will give you string starting from right position to applied length
SELECT
*
FROM #tblTest
WHERE YearNo=LEFT(#searchterm,4)
AND Id = REPLACE(RIGHT(#searchterm,LEN(#searchterm)-(CHARINDEX('/',(REPLACE(#searchterm, ' ', ''))))),'/','')
If your database compatibility could be 130 then You can Try String_Split ref https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql
Sql most long awaited function (as msdn says)
Declare #tbl table (id int Identity(1,1), value nvarchar(5))
Insert into #tbl ([value]) SELECT value from STRING_SPLIT(#searchstring,'/')
Declare #id int
Select #id = cast(value as int) from #tbl where id=2 --will give 1
Declare #value int
Select #id = cast(value as int) from #tbl where id=1 --ill give 2017
-- —now use them in sql
select * from table where YEAR=#value and ID = #id
You are going to screw up the performance if you do anything like below
select * from table where 'YEAR / ID' LIKE '%searchterm%'
Best way is you can split your search and supply to respective col
Declare #Search varchar(15)='2017/1'
Declare #Year int = (select LEFT(#Search,CHARINDEX('/',#search)-1))
Declare #month int = (select Right(#Search,(len(#search) -CHARINDEX('/',#search))))
select * from #temp where id=#month and year=#Year
Try this code :
select * from table where YEAR + ' / ' + ID LIKE '%searchterm%'
this query will run, but it will perform very poor.

SQL CSV as Query Results Column

I have the following SQL which queries a single table, single row, and returns the results as a comma separate string e.g.
Forms
1, 10, 4
SQL :
DECLARE #tmp varchar(250)
SET #tmp = ''
SELECT #tmp = #tmp + Form_Number + ', '
FROM Facility_EI_Forms_Required
WHERE Facility_ID = 11 AND EI_Year=2012 -- single Facility, single year
SELECT SUBSTRING(#tmp, 1, LEN(#tmp) - 1) AS Forms
The Facility_EI_Forms_Required table has three records for Facility_ID = 11
Facility_ID EI_Year Form_Number
11 2012 1
11 2012 10
11 2012 4
Form_number is a varchar field.
And I have a Facility table with Facility_ID and Facility_Name++.
How do I create a query to query all Facilites for a given year and produce the CSV output field?
I have this so far:
DECLARE #tmp varchar(250)
SET #tmp = ''
SELECT TOP 100 A.Facility_ID, A.Facility_Name,
(
SELECT #tmp = #tmp + B.Form_Number + ', '
FROM B
WHERE B.Facility_ID = A.Facility_ID
AND B.EI_Year=2012
)
FROM Facility A, Facility_EI_Forms_Required B
But it gets syntax errors on using #tmp
My guess is this is too complex a task for a query and a stored procedure may be need, but I have little knowledge of SPs. Can this be done with a nested query?
I tried a Scalar Value Function
ALTER FUNCTION [dbo].[sp_func_EI_Form_List]
(
-- Add the parameters for the function here
#p1 int,
#pYr int
)
RETURNS varchar
AS
BEGIN
-- Declare the return variable here
DECLARE #Result varchar
-- Add the T-SQL statements to compute the return value here
DECLARE #tmp varchar(250)
SET #tmp = ''
SELECT #tmp = #tmp + Form_Number + ', '
FROM OIS..Facility_EI_Forms_Required
WHERE Facility_ID = #p1 AND EI_Year = #pYr -- single Facility, single year
SELECT #Result = #tmp -- SUBSTRING(#tmp, 1, LEN(#tmp) - 1)-- #p1
-- Return the result of the function
RETURN #Result
END
The call
select Facility_ID, Facility.Facility_Name,
dbo.sp_func_EI_Form_List(Facility_ID,2012)
from facility where Facility_ID=11
returns
Facility_ID Facility_Name Form_List
11 Hanson Aggregates 1
so it is only returning the first record instead of all three. What am I doing wrong?
Try the following approach, which is an analogy to SO answer Concatenate many rows into a single text string. I hope it is correct, as I cannot try it out without having the schema and some demo data (maybe you can add schema and data to your question):
Select distinct A.Facility_ID, A.Facility_Name,
substring(
(
Select ',' + B.Form_Number AS [text()]
From Facility_EI_Forms_Required B
Where B.Facility_ID = A.Facility_ID
AND B.EI_Year=2012
ORDER BY B.Facility_ID
For XML PATH ('')
), 2, 1000) [Form_List]
From Facility A

Need to auto increment string in SQL Server 2012

Consider the table in SQL Server 2012
789-0000000
The above number will be consider as a string in SQL Server 2012, but whenever I update the record I need increment to 1.
For example:
When I update the record 1 it should increment to 789-0000001
When I update the record 2 it should increment to 789-0000002
Finally increment should done only 789-0000000
The best solution is to use
an ID INT IDENTITY(1,1) column to get SQL Server to handle the automatic increment of your numeric value
a computed, persisted column to convert that numeric value to the value you need
So try this:
CREATE TABLE dbo.YourTable
(ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
CompanyID AS '789-' + RIGHT('000000' + CAST(ID AS VARCHAR(7)), 7) PERSISTED,
.... your other columns here....
)
Now, every time you insert a row into dbo.YourTable without specifying values for ID or CompanyID:
INSERT INTO dbo.YourTable(Col1, Col2, ..., ColN)
VALUES (Val1, Val2, ....., ValN)
then SQL Server will automatically and safely increase your ID value, and CompanyID will contain values like 789-0000001, 789-0000002,...... and so on - automatically, safely, reliably, no duplicates.
DECLARE #base int = 0
UPDATE TableX
SET
TableX.Value = 'Prefix' + RIGHT('0000000' + CAST(#base AS nvarchar),7),
#base = #base + 1
FROM
TableX
you can split the string
e.g.:
SELECT Item
FROM dbo.SplitString('Apple,Mango,Banana,Guava', ',')
then cast it
e.g.:
SELECT CAST(YourVarcharCol AS INT) FROM Table
then manually increment it
e.g.:
DECLARE max_id INT
SET #max_id = (SELECT MAX(id) FROM source_table)
DECLARE cursor_name CURSOR FOR
SELECT columns, to, copy
FROM source_table
OPEN cursor_name
FETCH NEXT FROM cursor_name
INTO #columns, #to, #cop
at update
e.g.:
declare #i int = SELECT ISNULL(MAX(interfaceID),0) + 1 FROM prices
update prices
set interfaceID = #i , #i = #i + 1
where interfaceID is null
you can understand how complicate this is and why
the solution using a constant to store that prefix is right one.
Declare #str varchar(max) = '789-0000000'
Select
SUBSTRING ( #str ,0 ,CHARINDEX ( '-' ,#str ))
+'-'
+
(SUBSTRING ( #str ,(CHARINDEX ( '-' ,#str)+1) ,(7-LEN(CAST(SUBSTRING ( #str ,CHARINDEX ( '-' ,#str)+1,LEN(#str)) as int))
)
)+
CAST(CAST(SUBSTRING ( #str ,CHARINDEX ( '-' ,#str)+1,LEN(#str)) as int)+1 as varchar))
When #str='789-0001947'
Output #str= 789-0001948
You can write a update trigger on the table with above logic.

Split words with a capital letter in sql

Does anyone know how to split words starting with capital letters from a string?
Example:
DECLARE #var1 varchar(100) = 'OneTwoThreeFour'
DECLARE #var2 varchar(100) = 'OneTwoThreeFourFive'
DECLARE #var3 varchar(100) = 'One'
SELECT #var1 as Col1, <?> as Col2
SELECT #var2 as Col1, <?> as Col2
SELECT #var3 as Col1, <?> as Col2
expected result:
Col1 Col2
OneTwoThreeFour One Two three Four
OneTwoThreeFourFive One Two Three Four Five
One One
If this is not possible (or if too long) an scalar function would be okay as well.
Here is a function I created that is similar to the "removing non-alphabetic characters". How to strip all non-alphabetic characters from string in SQL Server?
This one uses a case sensitive collation which actively seeks out a non-space/capital letter combination and then uses the STUFF function to insert the space. This IS a scalar UDF, so some folks will immediately say that it will be slower than other solutions. To that notion, I say, please test it. This function does not use any table data and only loops as many times as necessary, so it will likely give you very good performance.
Create Function dbo.Split_On_Upper_Case(#Temp VarChar(1000))
Returns VarChar(1000)
AS
Begin
Declare #KeepValues as varchar(50)
Set #KeepValues = '%[^ ][A-Z]%'
While PatIndex(#KeepValues collate Latin1_General_Bin, #Temp) > 0
Set #Temp = Stuff(#Temp, PatIndex(#KeepValues collate Latin1_General_Bin, #Temp) + 1, 0, ' ')
Return #Temp
End
Call it like this:
Select dbo.Split_On_Upper_Case('OneTwoThreeFour')
Select dbo.Split_On_Upper_Case('OneTwoThreeFour')
Select dbo.Split_On_Upper_Case('One')
Select dbo.Split_On_Upper_Case('OneTwoThree')
Select dbo.Split_On_Upper_Case('stackOverFlow')
Select dbo.Split_On_Upper_Case('StackOverFlow')
Here is a function I have just created.
FUNCTION
CREATE FUNCTION dbo.Split_On_Upper_Case
(
#String VARCHAR(4000)
)
RETURNS VARCHAR(4000)
AS
BEGIN
DECLARE #Char CHAR(1);
DECLARE #i INT = 0;
DECLARE #OutString VARCHAR(4000) = '';
WHILE (#i <= LEN(#String))
BEGIN
SELECT #Char = SUBSTRING(#String, #i,1)
IF (#Char = UPPER(#Char) Collate Latin1_General_CS_AI)
SET #OutString = #OutString + ' ' + #Char;
ELSE
SET #OutString = #OutString + #Char;
SET #i += 1;
END
SET #OutString = LTRIM(#OutString);
RETURN #OutString;
END
Test Data
DECLARE #TABLE TABLE (Strings VARCHAR(1000))
INSERT INTO #TABLE
VALUES ('OneTwoThree') ,
('FourFiveSix') ,
('SevenEightNine')
Query
SELECT dbo.Split_On_Upper_Case(Strings) AS Vals
FROM #TABLE
Result Set
╔══════════════════╗
║ Vals ║
╠══════════════════╣
║ One Two Three ║
║ Four Five Six ║
║ Seven Eight Nine ║
╚══════════════════╝
If a single query is needed 26 REPLACE can be used to check every upper case letter like
SELECT #var1 col1, REPLACE(
REPLACE(
REPLACE(
...
REPLACE(#var1, 'A', ' A')
, ...
, 'X', ' X')
, 'Y', ' Y')
, 'Z', ' Z') col2
Not the most beautiful thing but it'll work.
EDIT
Just to add another function to do the same thing in a different way of the other answers
CREATE FUNCTION splitCapital (#param Varchar(MAX))
RETURNS Varchar(MAX)
BEGIN
Declare #ret Varchar(MAX) = '';
declare #len int = len(#param);
WITH Base10(N) AS (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7
UNION ALL SELECT 8 UNION ALL SELECT 9
), Chars(N) As (
Select TOP(#len)
nthChar
= substring(#param, u.N + t.N*10 + h.N*100 + th.N*1000 + 1, 1)
Collate Latin1_General_CS_AI
FROM Base10 u
CROSS JOIN Base10 t
CROSS JOIN Base10 h
CROSS JOIN Base10 th
WHERE u.N + t.N*10 + h.N*100 + th.N*1000 < #len
ORDER BY u.N + t.N*10 + h.N*100 + th.N*1000
)
SELECT #ret += Case nthChar
When UPPER(nthChar) Then ' '
Else ''
End + nthChar
FROM Chars
RETURN #ret;
END
This one uses the possibility of TSQL to concatenate string variable, I had to use the TOP N trick to force the Chars CTE rows in the right order
Build a Numbers table. There are some excellent posts on SO to show you how to do this. Populate it with values up the maximum length of your input string. Select the values from 1 through the actual length of the current input string. Cross join this list of numbers to the input string. Use the result to SUBSTRING() each character. Then you can either compare the resulting list of one-charachter values to a pre-populated table-valued variable or convert each character to an integer using ASCII() and choose only those between 65 ('A') and 90 ('Z'). At this point you have a list which is the position of each upper-case character in your input string. UNION the maximum length of your input string onto the end of this list. You'll see why in just a second. Now you can SUBSTRING() your input variable, starting at the Number given by row N and taking a length of (the Number given by row N+1) - (The number given by row N). This is why you have to UNION the extra Number on the end. Finally concatenate all these substring together, space-separated, using the algorithm of your choice.
Sorry, don't have an instance in front of me to try out code. Sounds like a fun task. I think doing it with nested SELECT statements will get convoluted and un-maintainable; better to lay it out as CTEs, IMHO.
I know that there are already some good answers out there, but if you wanted to avoid creating a function, you could also use a recursive CTE to accomplish this. It's certainly not a clean way of doing this, but it works.
DECLARE
#camelcase nvarchar(4000) = 'ThisIsCamelCased'
;
WITH
split
AS
(
SELECT
[iteration] = 0
,[string] = #camelcase
UNION ALL
SELECT
[iteration] = split.[iteration] + 1
,[string] = STUFF(split.[string], pattern.[index] + 1, 0, ' ')
FROM
split
CROSS APPLY
( SELECT [index] = PATINDEX(N'%[^ ][A-Z]%' COLLATE Latin1_General_Bin, split.[string]) )
pattern
WHERE
pattern.[index] > 0
)
SELECT TOP (1)
[spaced] = split.[string]
FROM
split
ORDER BY
split.[iteration] DESC
;
As I said, this isn't a pretty way to write a query, but I use things like this when I'm just writing up some ad-hoc queries where I would not want to add new artifacts to the database. You could also use this to create your function as an inline table valued function, which is always a tad nicer.
Please Try This:
declare #t nvarchar (100) ='IamTheTestString'
declare #len int
declare #Counter int =0
declare #Final nvarchar (100) =''
set #len =len( #t)
while (#Counter <= #len)
begin
set #Final= #Final + Case when ascii(substring (#t,#Counter,1))>=65 and
ascii(substring (#t,#Counter,1))<=90 then ' '+substring (#t,#Counter,1) else
substring (#t,#Counter,1) end
set #Counter=#Counter+1
end
print ltrim(#Final)