SQL Substring to fetch values which inside Bracket only i.e. () - sql

Might be easy for you expert but I am finding a challenge here-
My column data is as like below, I need to separate out the value which is inside bracket(). My string pattern would always be like this.
J Zeneta (A50103050); S Rao (B499487)
Output should be
Col1 Col2
A50103050 B499487

You can try this, it might need tweaking depending on your RDBMS, this is for SQLServer
select Left(value, CharIndex(')',value)-1) from (
select value from String_Split('J Zeneta (A50103050); S Rao (B499487)','(')
where value like '%)%'
)x
Edit
To have columns a simple case can yeild, like so
select max(case when rn=1 then Value end) Col1, max(case when rn=2 then value end) Col2 from (
select Left(value, CharIndex(')',value)-1) [Value], Row_Number() over (order by (select null)) rn from (
select value from String_Split('J Zeneta (A50103050); S Rao (B499487)','(')
where value like '%)%'
)x
)x
Edit 2
Using data from an existing table example
create table #Test (id int, col varchar(50))
insert into #Test select 1, 'J Zeneta (A50103050); S Rao (B499487)'
insert into #Test select 2, 'Bob Builder (12345); Mr Rambo (67890)'
select id, max(case when (rn % 2)=0 then Value end) Col1, max(case when (rn % 2)!=0 then value end) Col2 from (
select id, Left(value, CharIndex(')',value)-1) [Value], Row_Number() over (order by (select null)) rn from (
select id, value
from #Test t cross apply String_Split(t.col,'(')
where value like '%)%'
)x
)x
group by id

Related

Concatenated string split

I have a table Customer in SQL Server 2016 that has a text column with values
I=3;A=500;D=20210422
I would like to split the I=3,A=500 & D=20210422 into 3 columns in a new table or view.
One method is:
select t.*, s.*
from t cross apply
(select max(case when s.value like 'I=%' then stuff(s.value, 1, 2, '') end) as i,
max(case when s.value like 'A=%' then stuff(s.value, 1, 2, '') end) as a,
max(case when s.value like 'D=%' then stuff(s.value, 1, 2, '') end) as d
from string_split(t.col, ';') s
) s;
Here is a db<>fiddle.
Presumably these are just sample values and will vary? If you don't need to guarantee any particular ordering of the columns a simple solution is to use string_split and a conditional case expression to aggregate into new columns:
with v as (
select value, Row_Number() over (order by (select null)) rn
from String_Split('I=3;A=500;D=20210422',';')
)
select
Max(case when rn=1 then value end) Col1,
Max(case when rn=2 then value end) Col2,
Max(case when rn=3 then value end) Col3
from v
This works:
DECLARE #userData TABLE(
var1 varchar(30) NOT NULL,
var2 varchar(30) NOT NULL,
var3 varchar(30) NOT NULL
);
WITH CTE_Data
AS(
SELECT 'I=3,A=500,D=20210422' AS [MyData]
)
,CTE_Detaildata
AS(
SELECT
P.*
FROM(
SELECT
LEFT(v.[Value], 1) [ID],
v.[Value] AS [Data]
FROM CTE_Data AS d
CROSS APPLY STRING_SPLIT(d.[MyData], ',') AS v
)AS D
PIVOT(MIN(D.[Data]) FOR D.[ID] IN ([I],[A],[D])) AS P
)
INSERT INTO #userData(var1, var2, var3)
SELECT
d.[A],
d.[D],
d.[I]
FROM CTE_Detaildata AS d
SELECT * FROM #userData;

Select first occurrence of list item in table

I have a list like this example:
abc, efg, rty
and a table with following data:
1 abcd
2 efgh
3 abcd
4 rtyu
5 efgh
now I want to find the first-row which start with list item in the table. my expected result is:
1 abcd
2 efgh
4 rtyu
This is a complete script to do the job
Declare #v_List Table
(
Text nvarchar(100)
)
Declare #v_Data Table
(
Number int,
Text nvarchar(100)
)
Insert Into #v_List values(N'abc')
Insert Into #v_List values(N'efg')
Insert Into #v_List values(N'rty')
Insert Into #v_Data values(1, N'abcd')
Insert Into #v_Data values(2, N'efgh')
Insert Into #v_Data values(3, N'abcd')
Insert Into #v_Data values(4, N'rtyu')
Insert Into #v_Data values(5, N'efgh')
;with CTE as
(
Select D.Number,
D.Text,
ROW_NUMBER() OVER (PARTITION BY L.Text Order By D.Number) as Row_No
From #v_Data D
Join #v_List L
On D.Text like L.Text + '%'
)
Select CTE.Number,
CTE.Text
From CTE
Where CTE.Row_No = 1
select * from TableName
where Id in
(
select min(Id) from
(
select Id,
case
when Val like 'abc%' then 1
when Val like 'efg%' then 2
when Val like 'rty%' then 3
else 0 end temp
from TableName
)t where temp > 0
group by temp
)
You can use a windowed ROW_NUMBER to generate a sequential number by each different value, then just display the first one only.
;WITH RowNumbersByValue AS
(
SELECT
T.ID,
T.Value,
RowNumber = ROW_NUMBER() OVER (PARTITION BY T.Value ORDER BY T.ID)
FROM
YourTable AS T
)
SELECT
R.ID,
R.Value
FROM
RowNumbersByValue AS R
WHERE
R.Value IN ('abcd', 'efgh', 'rtyu') AND
R.RowNumber = 1
For SQL Server I prefer this version, which does not require a subquery:
SELECT TOP 1 WITH TIES ID, Value
FROM yourTable
WHERE Value LIKE 'abc%' OR Value LIKE 'efg%' OR Value LIKE 'rty%'
ORDER BY ROW_NUMBER() OVER (PARTITION BY Value ORDER BY ID);
SELECT * INTO #temp FROM (VALUES
(1 ,'abcd'),
(2 ,'efgh'),
(3 ,'abcd'),
(4 ,'rtyu'),
(5 ,'efgh'))a([id], [name])
You can use min and group by function
SELECT MIN(id), name FROM #temp GROUP BY name
You may use this, there are so many ways to achieve this, use whichever suits you better.
using subquery
select id, col from
(select Row_number() over (partition by col order by id) as slno, id, col from yourtable)
as tb where tb.slno=1
using cte
; with cte as (
select row_number() over (partition by col order by id) as Slno, id, col from table)
select id, col from cte where slno=1
using min
select Min(id) , col from table group by col
Note:-
In the end of any above mentioned query you may apply your where clause to filter your records as needed.

how to find all column records are same or not in group by column in SQL

How to find all column values are same in Group by of rows in table
CREATE TABLE #Temp (ID int,Value char(1))
insert into #Temp (ID ,Value ) ( Select 1 ,'A' union all Select 1 ,'W' union all Select 1 ,'I' union all Select 2 ,'I' union all Select 2 ,'I' union all Select 3 ,'A' union all Select 3 ,'B' union all Select 3 ,'1' )
select * from #Temp
Sample Table:
How to find all column value of 'Value' column are same or not if group by 'ID' Column.
Ex: select ID from #Temp group by ID
For ID 1 - Value column records are A, W, I - Not Same
For ID 2 - Value column records are I, I - Same
For ID 3 - Value column records are A, B, 1 - Not Same
I want the query to get a result like below
When all items in the group are the same, COUNT(DISTINCT Value) would be 1:
SELECT Id
, CASE WHEN COUNT(DISTINCT Value)=1 THEN 'Same' ELSE 'Not Same' END AS Result
FROM MyTable
GROUP BY Id
If you're using T-SQL, perhaps this will work for you:
SELECT t.ID,
CASE WHEN MAX(t.RN) > 1 THEN 'Same' ELSE 'Not Same' END AS GroupResults
FROM(
SELECT *, ROW_NUMBER() OVER(PARTITION BY ID, VALUE ORDER BY ID) RN
FROM #Temp
) t
GROUP BY t.ID
Usally that's rather easy: Aggregate per ID and count distinct values or compare minimum and maximum value.
However, neither COUNT(DISTINCT value) nor MIN(value) nor MAX(value) take nulls into consideration. So for an ID having value 'A' and null, these would detect uniqueness. Maybe this is what you want or nulls don't even occur in your data.
But if you want nulls to count as a value, then select distinct values first (where null gets a row too) and count then:
select id, case when count(*) = 1 then 'same' else 'not same' end as result
from (select distinct id, value from #temp) dist
group by id
order by id;
Rextester demo: http://rextester.com/KCZD88697

convert row into column with asc order in oracle

SELECT * FROM
(
SELECT TEST_NAME, SBNO, VAL
FROM TABLE1
)
PIVOT (
MAX(VAL)
FOR SBNO in (1 value1, 2 value2, 3 value3 ));
Output:
I want to show data in ascending order, like this:
2.3 , 2.4 , 2.5
but result is
2.3 , 2.5 , 2.4
This would do the trick. I have created a new SBNO column, ordering by test_name and value and then PIVOT operator will do the rest.
;with cte as (
select
test_name
,val
,'Value' + cast(ROW_NUMBER() over (partition by test_name order by test_name, val) as varchar(5)) as new_SBNO
from TABLE1
)
select *
from cte
pivot (
max(val)
for new_SBNO in (value1, value2, value3)
) pvt
I would do this using conditional aggregation:
select test_name,
max(case when seqnum = 1 then val end) as value_1,
max(case when seqnum = 2 then val end) as value_2,
max(case when seqnum = 3 then val end) as value_3
from (select t1.*,
row_number() over (partition by test_name order by val asc) as seqnum
from table1 t1
) t1
group by test_name;
You could express this with pivot. And in Oracle, pivot can even be a bit faster. I just find conditional aggregation to be more flexible and simpler to implement.

row convert to column in sql 2008

I want to convert a series of rows into a series of columns
create table #cusphone(cusid int,cusph1 int)
insert into #cusphone values(1,48509)
insert into #cusphone values(1,48508)
insert into #cusphone values(1,48507)
insert into #cusphone values(2,48100)
so that the output is like this
1 48509 48508 48507
2 48100 null null
You can use the same approach of rank() and then use the new PIVOT function as follows:
with cusCte as(
select cusid,cusph1,RANK() over (partition by cusid order by cusph1) r
from #cusphone)
SELECT cusid, [1] AS C1, [2] AS C2, [3] AS C3
FROM
(SELECT cusid,cusph1,r
FROM cusCte) p
PIVOT
(
MIN (cusph1)
FOR r IN
( [1], [2], [3] )
) AS pvt;
You did not specify the rules by which something should appear in the first column vs the second column so I guessed that this is based on the occurrence (and thus sorting) of the cusph1 value.
With RankedItems As
(
Select cusid, cusph1
, ROW_NUMBER() OVER( PARTITION BY cusid ORDER BY cusph1 DESC) As Num
From #cusphone
)
Select cusid
, Min(Case When Num = 1 Then cusph1 End) As Col1
, Min(Case When Num = 2 Then cusph1 End) As Col2
, Min(Case When Num = 3 Then cusph1 End) As Col3
From RankedItems
Group By cusid