How to insert character in between a string in SQL - sql

I have a col1 in tbl1 which has data as under:
C:\ABC\1245_PQR\125\xyz\ROW20MAOSAD12\
now I want to insert a '\' after C:\ABC\1245_PQR\125\xyz\ROW and before '20MAOSAD12\'
and the data format is same but it changes in all row, for example -
C:\ABC\1245_PQR\125\xyz\ROW20MAOSAD12\
C:\ABC\3456_ADR\515\xpo\ROWadMAOSAD23\
C:\ABC\1547_DFR\255\RDS\ROW14SDFS15\
Can someone please help.
Thanks

You can use replace function
SELECT REPLACE('C:\ABC\1245_PQR\125\xyz\ROW20MAOSAD12\', '\ROW', '\ROW\')
To be more precise
SELECT REPLACE(col1, '\ROW', '\ROW\') from tbl1

Alternatively you could consider the STUFF operator:
STUFF ( character_expression , start , length , replaceWith_expression )
SELECT STUFF('C:\ABC\1245_PQR\125\xyz\ROW20MAOSAD12\',28,0, '\')
SELECT STUFF('SomeColumn',28,0, '\') FROM SomeTable WHERE SomeColumn=SomeValue

Also, I made this one - a bit lengthy
-- Step 1
Select all rows that have ...xyz.... in col1 and col2 is xyz
select * from tbl where col2 = 'row' and col1 like '%xyz%'
-- Step 2
-- From the rows above, calculate the start index of ...xyz....... in col1
select charindex('xyz', col1) from (select col1 from tbl where col2 = 'xyz' and col1 like '%xyz%') tmp
-- Step 3
-- Split the col1 from CharIndex + 3 (size of xyz)
select left(col1, charindex('xyz', col1) + 2 ), substring(col1, charindex('xyz', col1) + 3, LEN(col1) ), ( left(col1, charindex('xyz', col1) + 2 ) + '\' + substring(col1, charindex('xyz', col1) + 3, LEN(col1) ))
from (select col1 from tbl where name = 'xyz' and col1 like '%xyz%') tmp
-- Step 4
-- Update !!
update tbl
SET col1 = ( left(col1, charindex('xyz', col1) + 2 ) + '\' + substring(col1, charindex('xyz', col1) + 3, LEN(col1) ))
where col2 = 'xyz' and col1 like '%xyz%' and col1 not like '%xyz\%'

Related

SQL Substring and Charindex

I have 111-1001-0000-0000 this record in one column and 453200-0000-000 in second column
I want output as 111-1001-0000-453200-0000-0000-000
That means 111-1001-0000 from 1st column and 453200 from 2nd column and again 0000 from 1st column and 0000-000
from 2nd column
I tried below query but getting 111-1001-453200-0000-0000-000.
-0000 is missing from 1st column
Declare #1stcolumn nvarchar(30),#2ndcolumn nvarchar(30)
set #1stcolumn='111-1001-0000-0000'
set #2ndcolumn='453200-0000-000'
select substring(#1stcolumn,1,charindex(right(#1stcolumn,charindex('-',reverse(#1stcolumn))),#1stcolumn))
+substring(#2ndcolumn,1,charindex('-',#2ndcolumn))+reverse(substring(reverse(#1stcolumn),0,charindex('-',reverse(#1stcolumn))))
+'-'+substring(#2ndcolumn,charindex('-',#2ndcolumn)+1,len(#2ndcolumn))
find the position where to split column 1 and column2. Use LEFT() and RIGHT() to split the string and then concatenate back in the order that you want
; with tbl as
(
select col1 = #1stcolumn, col2 = #2ndcolumn
)
select *,
c1.s1 + '-' + c2.s1 + '-' +c1.s2 + '-' + c2.s2
from tbl t
cross apply
(
select s1 = left(col1, p - 1),
s2 = right(col1, len(col1) - p)
from (
-- find the position of 3rd '-' by cascading charindex
select p = charindex('-', col1,
charindex('-', col1,
charindex('-', col1) + 1) + 1)
) p
) c1
cross apply
(
select s1 = left(col2, p - 1),
s2 = right(col2, len(col2) - p)
from (
select p = charindex('-', col2)
) p
) c2
A little modification in first substring. To get correct length I used LEN .
select substring(#1stcolumn,1,(Len(#1stcolumn) - charindex('- ',REVERSE(#1stcolumn)) + 1))
+substring(#2ndcolumn,1,charindex('-',#2ndcolumn))
+reverse(substring(reverse(#1stcolumn),0,charindex('-',reverse(#1stcolumn))))
+'-'+substring(#2ndcolumn,charindex('-',#2ndcolumn)+1,len(#2ndcolumn))
I'd probably do with with PARSENAME as it's quite concise then:
WITH YourTable AS(
SELECT '111-1001-0000-0000' AS Column1,
'453200-0000-000' AS Column2)
SELECT CONCAT_WS('-',PN.C1P1,PN.C1P2,PN.C1P3,PN.C2P1,PN.C1P4,PN.C2P2,PN.C2P3) AS NewString
FROM YourTable YT
CROSS APPLY (VALUES(REPLACE(YT.Column1,'-','.'),REPLACE(YT.Column2,'-','.')))R(Column1,Column2)
CROSS APPLY (VALUES(PARSENAME(R.Column1,4),PARSENAME(R.Column1,3),PARSENAME(R.Column1,2),PARSENAME(R.Column1,1),PARSENAME(R.Column2,3),PARSENAME(R.Column2,2),PARSENAME(R.Column2,1)))PN(C1P1,C1P2,C1P3,C1P4,C2P1,C2P2,C2P3);
WITH
test AS
(
select '111-1001-0000-0000' as col1, '453200-0000-000' as col2
)
,cte as
(
select
col1,
col2,
substring
(
col1,
0,
len(col1)-charindex('-',reverse(col1))
) as part1,
substring
(
col2,
0,
len(col2)-charindex('-',col2) - 1
) as part2
from test
),
cte2 as
(
select
part1,
part2,
substring
(
reverse(col1),
0,
charindex('-',reverse(col1))
) as part3,
substring
(
col2,
charindex('-',col2)+1,
len(col2)-charindex('-',col2)+1
) as part4
from cte
)
select part1+'-'+part2+'-'+part3+'-'+part4
from cte2

MSSQL select lowest but not NULL/zero value from 25 columns

I have 25 (numeric) columns in one table in MSSQL and I need select lowest value, but not NULL or 0 value.
Columns are named like "%_price" (aaa_price, bbb_price, ccc_price...).
Some columns contains 0 or NULL value.
Example:
table (aaa_price, bbb_price, ccc_price, ddd_price, eee_price, fff_price)
value (NULL, 0, 324.23, 162.50, NULL, 1729.72 )
Right result:
162.50
I can use some "brute force" method like:
SELECT CASE
WHEN Col1 <= Col2 AND Col1 <= Col3 AND Col1 <= Col4 AND Col1 <= Col5 THEN Col1
WHEN Col2 <= Col3 AND Col2 <= Col4 AND Col2 <= Col5 THEN Col2
WHEN Col3 <= Col4 AND Col3 <= Col5 THEN Col3
WHEN Col4 <= Col5 THEN Col4
ELSE Col5
END AS [Min Value] FROM [Your Table]
But its insane with 25 columns... is there any better solution?
Thank You!
Cross apply can be good option in this case:
select
*
from
myTable
cross apply (select
minVal = min(val)
from (
values (aaa_price),(bbb_price),(...)
) t(val) where val > 0
) q
Edit:
You have to use dynamic SQL if you want to get column names from INFORMATION_SCHEMA.COLUMNS table.
declare #sql varchar(8000)
declare #cols varchar(8000)
select #cols =
stuff((
SELECT
',(' + COLUMN_NAME + ')'
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = 'mytable'
AND TABLE_SCHEMA='dbo'
AND COLUMN_NAME LIKE '%price'
for xml path('')
), 1, 1, '')
set #sql = 'select
*
from
mytable
cross apply (select
minVal = min(val)
from (
values ' + #cols + '
) t(val) where val > 0
) q'
exec (#sql)
You can create a dynamic SQL statement and execute it in the following form
declare #tablename sysname = 'MultipleNumericColumns'
declare #sql nvarchar(max)
select #sql = isnull(#sql + ' union all ','') + '
SELECT ' + name + ' as colname from ' + #tablename
from sys.all_columns
where
object_id = OBJECT_ID(#tablename)
set #sql = '
select min(colname)
from (
' + #sql + '
) t
where colname > 0'
EXECUTE(#sql)
You can realize that first I get the column names from system view
You can exclude columns that you don't want or use a pattern like name like '%price% etc at this step
Then I build a dynamic SQL query into a string variable as sql command
Please note that I use WHERE clause for greater than 0, etc
Final step is execution with EXECUTE command
Use UNPIVOT
SELECT Min(VALUE)
FROM (
SELECT Col1, Col2, Col3...
FROM YourTable
) t
UNPIVOT (VALUE FOR ITEM IN (Col1, Col2, Col3...)) u
WHERE VALUE != 0

SQL Server : Reuse calculated variable in select clause

I have the following table structure:
col1 col2 col3 col4
-------------------------------
aK Mbcd ABc defgh
col2, col3 and col4 columns are of type varchar(100) and col1 has type varchar(500).
I need a select query to have the output as following
col1 col2 col3 col4
-------------------------------
aK,Mb cd,A Bc,d efgh
Logic is explained as mentioned below:
In the result, Col2, col3 and col4 can have maximum 4 characters but col1 can have more than 4 characters upto 100.
If any column has more characters, last 4 characters will be retained in the same column and other extra columns will be concatenated with previous column's value separated by comma , and the same rule will be applied on the concatenated values as well.
I've written the following T-SQL statement. It works fine for last two columns. But I want to use new calculated value of col3 to strip out extra characters after adding some from col4
SELECT
CASE
WHEN X.Col4Length > 4
THEN concat(X.col3, ',', substring(x.col4, 0, X.Col4Length - 3))
ELSE X.col3
END AS col3,
CASE
WHEN X.Col4Length > 4
THEN substring(x.col4, X.Col4Length - 3, x.Col4Length)
ELSE X.col4
END AS col4
FROM
(SELECT
Col1, Col2, Col3, Col4,
Len(Col1) AS Col1Length,
Len(Col2) AS Col2Length,
Len(Col3) AS Col3Length,
Len(Col4) AS Col4Length
FROM
mytable) X
My try with a simple sub-query
with t1 as (
select 'aK' col1, 'Mbcd' col2, 'ABc' col3, 'defgh' col4
---
SELECT LEFT(col, LEN(col) - 12) col1,
RIGHT(LEFT(col, LEN(col) - 8), 4) col2,
RIGHT(LEFT(col, LEN(col) - 4), 4) col3,
RIGHT(col, 4) AS col4
FROM
(
SELECT col1+','+col2+','+col3+','+col4 AS col
FROM t1
) t;
You want to reuse calculated variables
There are two set-based /inline / adhoc approaches (and many more ugly procedural):
CTEs to do this for the whole set in advance
CROSS APPLY for the same on row level
Try it like this (CTE approach)
DECLARE #tbl TABLE(col1 VARCHAR(100),col2 VARCHAR(100),col3 VARCHAR(100),col4 VARCHAR(100));
INSERT INTO #tbl VALUES
('aK','Mbcd','ABc','defgh')
,('123456','abc','3456','123456789');
WITH ResolveCol4 AS
(
SELECT *
,RIGHT(col4,4) AS Col4_resolved
,col3 + ',' + CASE WHEN LEN(col4)>4 THEN SUBSTRING(col4,1,LEN(col4)-4) ELSE '' END AS col3_New
FROM #tbl
)
,ResolveCol3 AS
(
SELECT *
,RIGHT(col3_New,4) AS Col3_resolved
,col2 + ',' + CASE WHEN LEN(col3_New)>4 THEN SUBSTRING(col3_New,1,LEN(col3_New)-4) ELSE '' END AS col2_New
FROM ResolveCol4
)
,ResolveCol2 AS
(
SELECT *
,RIGHT(col2_New,4) AS Col2_resolved
,col1 + ',' + CASE WHEN LEN(col2_New)>4 THEN SUBSTRING(col2_New,1,LEN(col2_New)-4) ELSE '' END AS col1_New
FROM ResolveCol3
)
SELECT col1_new,Col2_resolved,Col3_resolved,Col4_resolved
FROM ResolveCol2
The result
aK,Mb cd,A Bc,d efgh
123456,abc,34 56,1 2345 6789

Is there any way to print the Query result horizontally in Oracle DB

Select * from TABLENAME WHERE "CLAUSE"
It will print the result in a single row.
Col 1 Col 2 ...... Col N
Val 1 Val 2 ...... Val N
I need
Col 1 Val 1
Col 2 Val 2
.
.
.
Col N Val N
A little time consuming to do on a regular basis, but:
select COL_NAME, COL_DATA
from (SELECT * FROM table_name
WHERE clause)
unpivot ( COL_NAME FOR COL_DATA IN ( COL1 as 'COL1'
,COL2 as 'COL2'
,COL3 as 'COL3'
,COL4 AS 'COL4')
)
Bear in mind that you also need to cast all of the values to the same data-type as Oracle won't mix datatypes in the same column, so if COL1-3 are number, but COL4 is varchar, then you would
select COL_NAME, COL_DATA
from (SELECT * FROM table_name
WHERE clause)
unpivot ( COL_NAME FOR COL_DATA IN ( TO_CHAR(COL1) as 'COL1'
,TO_CHAR(COL2) as 'COL2'
,TO_CHAR(COL3) as 'COL3'
,COL4 AS 'COL4')
)
select 'col 1', col1 from TABLENAME WHERE "CLAUSE"
UNION ALL
select 'col 2', col2 from TABLENAME WHERE "CLAUSE"
UNION ALL
...
select 'col n', coln from TABLENAME WHERE "CLAUSE"
order by 1

Complex summing in SQL

I'm working with a relational database that uses SQL99.
I have a series of 10 columns, each of the 10 columns contain a number value.
I need to sum each column individually and then take those sums and add them all together to get an overall sum. Then I must divide the overall sum by 15.
I've tried every format I can think of and have yet to return any results. I have no idea what the syntax should look like.
SELECT SUM(col1), SUM(col2)..., SUM(col1 + col2 + col3 + col4...)/15
FROM TABLENAME
GROUP BY 1=1
select
sum(col1) as sum1,
sum(col2) as sum2,
sum(col3) as sum3,
sum(col4) as sum4,
sum(col5) as sum5,
sum(col6) as sum6,
sum(col7) as sum7,
sum(col8) as sum8,
sum(col9) as sum9,
sum(col10) as as sum10,
sum( col1 + col2 + col3 + col4 + col5 + col6 + col7 + col8 + col9 + col10) as overallsum,
sum( col1 + col2 + col3 + col4 + col5 + col6 + col7 + col8 + col9 + col10) / 15 as dividedsum
from
tablename
SELECT SUM(subsum) / 15 FROM (
SELECT SUM(column1) AS subsum
FROM table
UNION ALL
SELECT SUM(column2) AS subsum
FROM table
UNION ALL
...
SELECT SUM(column10) AS subsum
FROM table
)