Parsing of String in sql - sql-server

I have data coming as
**Column**
A/B(D)C
Need output as
Column1 Column2 Column3 Column4
A B D C
Tried to use String Split where i can split only one delimiter which is not as expected

Please try the following solution.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, tokens VARCHAR(100));
INSERT #tbl (tokens) VALUES
('A/B(D)C'),
('Miami/Orlando(Denver)Hollywood');
-- DDL and sample data population, start
SELECT t.*
, col1 = PARSENAME(c,4)
, col2 = PARSENAME(c,3)
, col3 = PARSENAME(c,2)
, col4 = PARSENAME(c,1)
FROM #tbl AS t
CROSS APPLY (VALUES (REPLACE(REPLACE(REPLACE(tokens,'/','.'),'(','.'),')','.'))) AS t1(c);
-- SQL Server 2017 onwards
--CROSS APPLY (VALUES (TRANSLATE(tokens,'/()','...'))) AS t1(c);
Output
ID
tokens
col1
col2
col3
col4
1
A/B(D)C
A
B
D
C
2
Miami/Orlando(Denver)Hollywood
Miami
Orlando
Denver
Hollywood

Related

Count how many times a word exist in column

I have a table 1:
CREATE TABLE table1
INSERT INTO table1 values('XYZ')
INSERT INTO table1 values('ABC')
INSERT INTO table1 values('XYZ~ABC~AAA')
INSERT INTO table1 values('123')
Then, I have string 'ABC~XYZ~123'. I need to split this string into each word by using SQL:
Select VALUE FROM STRING_SPLIT('ABC~XYZ~123','~')
The return is table2
ABC
XYZ
123
I want to count how many times each word in table2 existed in table 1
The expected output is
ABC|3
XYZ|2
123|1
Any ideas on this?
If I understand your case correctly, the next statement may help:
Text and table:
DECLARE #text varchar(100) = 'ABC~XYZ~123'
CREATE TABLE Data (
Id int,
[Text] varchar(100)
)
INSERT INTO Data
(Id, [Text])
VALUES
(1, 'XYZ'),
(2, 'ABC'),
(3, 'XYZ~ABC~AAA'),
(4, '123~ABC')
Statement:
SELECT t.[value] AS [Word], j.[Count]
FROM STRING_SPLIT(#text, '~') t
LEFT JOIN (
SELECT s.[value], COUNT(*) AS [Count]
FROM Data d
CROSS APPLY STRING_SPLIT(d.[Text], '~') s
GROUP BY s.[value]
) j ON t.[value] = j.[value]
Result:
-----------
Word Count
-----------
ABC 3
XYZ 2
123 1
Apart from the suggestions as in comment you can use Count() function as below. But storing in this format will give you difficulty for the extraction as well as in join with the other tables.
Select T1Value, Count(*) as [NoCount] from(
Select table1.Value as T1Value, Value FROM STRING_SPLIT('ABC~XYZ~123','~')
inner join table1 on Value = table1.Value
)a group by T1Value
Edit
CREATE TABLE table1(
TableValue varchar(max)
);
INSERT INTO table1 (TableValue) values ( 'XYZ');
INSERT INTO table1 ( TableValue) values ( 'ABC');
INSERT INTO table1 ( TableValue) values ( 'XYZ~ABC~AAA');
INSERT INTO table1 ( TableValue) values ( '123~ABC');
SELECT b.value
,Count(*)
FROM (
SELECT VALUE
FROM STRING_SPLIT('ABC~XYZ~123', '~')
) a
INNER JOIN (
SELECT *
FROM table1
CROSS APPLY STRING_SPLIT(TableValue, '~')
) b ON a.Value = b.Value
GROUP BY b.Value
Here is the given Live Demo on db <> fiddle
Setup
create table STRINGS (ID int, STRINGS varchar(max));
insert into STRINGS (ID, STRINGS) values (1, 'XYZ');
insert into STRINGS (ID, STRINGS) values (1, 'ABC');
insert into STRINGS (ID, STRINGS) values (1, 'XYZ~ABC~AAA');
insert into STRINGS (ID, STRINGS) values (1, '123~ABC');
declare #VALUES varchar(max) = 'XYZ~ABC~123';
Calculation :
select V1.VALUE, count(STRINGS.ID)
from string_split(#VALUES,'~') V1
cross join STRINGS
outer apply string_split(STRINGS.STRINGS,'~') V2
where V2.VALUE = V1.VALUE
group by V1.VALUE
Result
-----------
Value Num
-----------
ABC 3
XYZ 2
123 1
Live exemple :
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=15b95efcf69ea98fafbb7dda1c624551

Get values NOT IN Table1 when join with Table2

I have two tables as below:
Table1:
Col1 Col2
834 2
834 3
834 5
877 1
877 2
877 5
900 10
900 2
900 3
Table2:
Col3
1
10
Expected Output:
Col1 Col3
834 1
834 10
877 10
900 1
This is what I have done so far:
select distinct t1.Col1,A.Col3
from Table1
cross apply
(select * from Table2 left join Table1 on Col2 = Col3) A
order by t1.Col1,A.Col3
I have been trying lot using join, cross apply and other sql function to get me the expected output. Any help is appreciated.
Logic:
I want to get the values of Col1 of Table1 for which Col3 does not matches with col2 of Table1.
For Eg: Values 1 and 10 of Col3 of table2 is not there for value 834 of col1 of table1. Hence there are two rows for 834, one with value 1 and other with 10.
Please try with the below code snippet.
DECLARE #Table1 TABLE(
Col1 INT NOT NULL,
Col2 INT NOT NULL
);
INSERT INTO #Table1 VALUES(834 , 2)
INSERT INTO #Table1 VALUES(834 , 3)
INSERT INTO #Table1 VALUES(834 , 5)
INSERT INTO #Table1 VALUES(877 , 1)
INSERT INTO #Table1 VALUES(877 , 2)
INSERT INTO #Table1 VALUES(877 , 5)
INSERT INTO #Table1 VALUES(900 , 10)
INSERT INTO #Table1 VALUES(900 , 2)
INSERT INTO #Table1 VALUES(900 , 3)
DECLARE #Table2 TABLE(
Col3 INT NOT NULL
);
INSERT INTO #Table2 VALUES(1)
INSERT INTO #Table2 VALUES(10)
SELECT a.Col1,a.Col3 FROM (SELECT DISTINCT a.Col1,b.Col3 FROM #Table1 a,#Table2 b
WHERE a.Col2 <> b.Col3) a
LEFT JOIN #Table1 c on a.Col1 = c.Col1 and a.Col3 = c.Col2
WHERE c.Col1 is null
I doubt you need any join in here. All you want to select from table1 are the rows with matching value in table2. Something like this :
Select distinct col1, col2 from table1
Where col2 not in (select col3 from table2)
select a.col1, a.col2
from Table1 a
where not exists(select * from Table2 b where a.col1 = b.col3)
This may work...

How to get column name of particular value in sql server 2008

I want to get column name of particular value. I have table CurrentReport having unique id from which i can get particular row now from the values of that row i want to get the name of columns that i need to update .
I think you want a list of column names that match a particular value.
To do that you can create a XML column in a cross apply for each row and the use nodes() in a second cross apply to shred on the elements that has the value you are looking for.
SQL Fiddle
MS SQL Server 2014 Schema Setup:
create table dbo.CurrentReport
(
ID int primary key,
Col1 varchar(10),
Col2 varchar(10),
Col3 varchar(10)
);
go
insert into dbo.CurrentReport(ID, Col1, Col2, Col3) values(1, 'Value1', 'Value2', 'Value3');
insert into dbo.CurrentReport(ID, Col1, Col2, Col3) values(2, 'Value2', 'Value2', 'Value2');
insert into dbo.CurrentReport(ID, Col1, Col2, Col3) values(3, 'Value3', 'Value3', 'Value3');
Query 1:
-- Value to look for
declare #Value varchar(10) = 'Value2';
select C.ID,
-- Get element name from XML
V.X.value('local-name(.)', 'sysname') as ColumnName
from dbo.CurrentReport as C
cross apply (
-- Build XML for each row
select C.*
for xml path(''), type
) as X(X)
-- Get the nodes where Value = #Value
cross apply X.X.nodes('*[text() = sql:variable("#Value")]') as V(X);
Results:
| ID | ColumnName |
|----|------------|
| 1 | Col2 |
| 2 | Col1 |
| 2 | Col2 |
| 2 | Col3 |

How to select from a table function along with columns from another table

I have a function that returns a table. It takes one parameter and returns one row.
I want to select the values from that function along with columns from another table in the same SELECT staement.
Something like this:
SELECT a.col1, a.col2, b.col1, b.col2
FROM tab1 a INNER JOIN
func1(a.col1) b ON a.col1 = b.col1
WHERE a.col1 IN (123,456,789)
This doesn't work, but is there a way I can do this.
So, for example, if func 1 returns the following for each of the three values in the example:
col1 col2
123 abc
456 def
789 xyz
then I am expecting something like the following results from my query:
col1 col2 col1 col2
123 xxx 123 abc
456 yyy 456 def
789 zzz 789 xyz
I can do it like this, but I'd rather not call the function multiple times for each column I want from the function:
SELECT col1, col2, (SELECT col1 FROM func1(a.col1)), (SELECT col2 FROM func1(a.col1))
FROM tab1 a
WHERE a.col1 IN (123,456,789)
this code is true
alter FUNCTION GETTABLE()
RETURNS #rtnTable TABLE
(
SUM_CD nvarchar(15) NOT NULL,
Name nvarchar(255) NOT NULL
)
AS
BEGIN
DECLARE #TempTable table (SUM_CD Nvarchar(15), name nvarchar(255))
insert into #TempTable(SUM_CD,name) values ('300001','Ahmed')
insert into #TempTable(SUM_CD,name) values ('300002','Mohamed')
insert into #rtnTable
select * from #TempTable
return
END
select * from GLSUMS g inner join dbo.gettable() s on s.SUM_CD=g.SUM_CD
in SQL SERVER 2012

How to filter rows by values of one column?

I need to get several columns form sql query. Then I have to filter this answer by the "distinct" values of one column, but in the output I need to have all columns, not only this which values has to be distinct. Can anybody help me? Order by clause is not an answer for me.
A,B,C,D
E,F,G,H
I,J,C,L
M,N,Z,H
Above is a simple rows output. Please have a look onto 3rd column. Let's assume that we don't know how many rows do we have. I need to select only rows which has distinct value in 3rd column. (C,G,Z) - We need to filter anyone from "C" rows.
I've arbitrarily chosen to use col1 to break ties on col3. You can adjust the order by portion of the partition to suit your needs.
/* Set up test data */
declare #test table (
col1 char(1),
col2 char(1),
col3 char(1),
col4 char(1)
)
insert into #test
(col1, col2, col3, col4)
select 'A','B','C','D' union all
select 'E','F','G','H' union all
select 'I','J','C','L' union all
select 'M','N','Z','H'
/* Here's the query */
;with cteRowNumber as (
select col1, col2, col3, col4,
row_number() over (partition by col3 order by col1) as RowNumber
from #test
)
select col1, col2, col3, col4
from cteRowNumber
where RowNumber = 1
Returns
col1 col2 col3 col4
----------------------------
A B C D
E F G H
M N Z H
ROLL UP or CUBE could be helpful for your problem, since they can aggregate (i.e. subtotal) data based on the GROUP BY and still return the individual rows.

Resources