Select unique values of an xml attribute - sql

I have a temp table with one column of xml type.
How can I write a single SELECT query to list all unique values of attribute 'z'
CREATE TABLE #TEST3 ([Data] XML)
INSERT INTO #TEST3 VALUES ('<r><a z="1" /> <a z="2" /></r>')
INSERT INTO #TEST VALUES ('<r><b z="2" /><b z="3" /></r>')
INSERT INTO #TEST3 VALUES ('<r><c z="3"><c z="4" /></c></r>')

Select
Distinct t.m.value( '#z[1]', 'varchar(max)' ) ZAttribute
From
#Test3 tempTable
Cross Apply tempTable.Data.nodes( '/your/node/path/here' ) t(m)

Related

SQL TABLE to JSON without SQL Column Information

I am trying to Parse Table data into JSON and in the process want to skip the Table Column Names in the Post conversion to JSON. Below is the sample Snippet.
DECLARE #table1 TABLE (k1 nvarchar(max), v1 nvarchar(max))
-- Note k1 is unique
INSERT INTO #table1 (k1,v1) VALUES( 'Apple', 'One')
INSERT INTO #table1 (k1,v1) VALUES( 'Banana', 'Two')
INSERT INTO #table1 (k1,v1) VALUES( 'Orange', 'Three')
SELECT k1, v1 FROM #table1
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
--output: {"k1":"Apple","v1":"One"},{"k1":"Banana","v1":"Two"},{"k1":"Orange","v1":"Three"}
-- Expected: {"Apple","One"},{"Banana","Two"},{"Orange","Three"}
Appreciate direction!
--string concatenation&aggregation (string_agg() for sql2017&later or for xml path() for sql2016)
select string_agg(concat('{"', string_escape(k1, 'json'), '":"', string_escape(v1, 'json'), '"}'), ',') /*within group (order by k1)*/
from #table1

Make all word with special character list in each position SQL server

I have a table similar this
CREATE TABLE [dbo].[Test](
[harfno] INT,
[harf] NCHAR(1) NULL
)
and below values row count and harfno is variable
INSERT INTO [dbo].[Test]([harfno],[harf]) VALUES (1,'a')
INSERT INTO [dbo].[Test]([harfno],[harf]) VALUES (2,'b')
INSERT INTO [dbo].[Test]([harfno],[harf]) VALUES (3,'c')
INSERT INTO [dbo].[Test]([harfno],[harf]) VALUES (3,'d')
INSERT INTO [dbo].[Test]([harfno],[harf]) VALUES (4,'e')
INSERT INTO [dbo].[Test]([harfno],[harf]) VALUES (5,'f')
INSERT INTO [dbo].[Test]([harfno],[harf]) VALUES (5,'g')
INSERT INTO [dbo].[Test]([harfno],[harf]) VALUES (5,'h')
I need output like this: all word with special character list in each position ,position is harfno in each harfno maybe I have more than on char
word
abcef
abceg
abceh
abdef
abdeg
abdeh
Naive approach:
SELECT t1.harf + t2.harf+ t3.harf+ t4.harf+ t5.harf AS word
FROM Test t1, Test t2, Test t3, Test t4, Test t5
WHERE t1.harfno=1
AND t2.harfno=2
AND t3.harfno=3
AND t4.harfno=4
AND t5.harfno=5;
DBFidlde Demo
EDIT:
Recursive CTE:
WITH cte(harf, harfno) AS (
SELECT CAST(harf AS NVARCHAR(MAX)), 1 AS harfno
FROM Test
WHERE harfno=1
UNION ALL
SELECT c.harf + t.harf,t.harfno
FROM Test t
JOIN cte c
ON t.harfno = c.harfno+1
)
SELECT *
FROM cte
WHERE LEN(harf)= (SELECT MAX(harfno) FROM cte)
ORDER BY harf
--OPTION(MAXRECURSION nn)
DBFiddle Demo

How to make a efficient comma separator

This is my table
create table #t(id varchar(10),value varchar(10))
insert into #t values('0001','a'),('0001','b'),('0002','c'),('0002','d')
I need a efficient method of making csv
id value
0001 a,b
0002 c,d
try this!
using Stuff with xml path('')
select id,
stuff(
(
select ',' + value from #t t1 where t1.id=t2.id for xml path(''),type).value('.','varchar(max)'),1,1,'') from #t t2
group by t2.id
Hello below given requirement both columns are in VARCHAR . So we can use SUBSTRING FUNCTION and CROSS APPLY to get Expected output
DECLARE #t TABLE (ID VARCHAR(10) ,VALUE VARCHAR(10) )
INSERT INTO #t (ID,VALUE)VALUES ('0001','a')
INSERT INTO #t (ID,VALUE)VALUES ('0001','b')
INSERT INTO #t (ID,VALUE)VALUES ('0002','c')
INSERT INTO #t (ID,VALUE)VALUES ('0002','d')
INSERT INTO #t (ID,VALUE)VALUES ('0003','e')
INSERT INTO #t (ID,VALUE)VALUES ('0003','f')
SELECT [Id],
SUBSTRING(d.Value,1, LEN(d.Value) - 1) VALUE
FROM
(
SELECT DISTINCT [Id]
FROM #t
) a
CROSS APPLY
(
SELECT Value + ', '
FROM #t AS B
WHERE A.[Id] = B.[Id]
FOR XML PATH('')
) D (Value)

SQL Substring on varying column

I have a database table with a column METADATA. This METADATA may or may not contain a string. Here's the sample string:
StudentID:1234,StudentName:TestName,StudentNickName:TestNName,StudentLevel:5
Now, I want to extract the StudentNickName:TestName if it exists. Please note of the following constraint:
METADATA column doesn't always contain a value
METADATA column can contain a value without the StudentNickName clause
The StudentNickName: is fixed, while the TestNName varies per row.
For mssql 2005+
declare #t table(metadata varchar(200))
insert #t values('StudentID:1234,StudentName:TestName,StudentNickName:TestNName,StudentLevel:5')
insert #t values('')
insert #t values('StudentID:1234,StudentName:Thomas,StudentNickName:Tom,StudentLevel:3')
select left(b.a, patindex('%_,%', b.a)) StudentNickName
from #t t cross apply
(select right(metadata, patindex('%_:emaNkciNtnedutS%'
, reverse('X'+ metadata)))+',' a) b
Result:
StudentNickName
---------------
TestNName
Tom
Works in Sql Server
DECLARE #test TABLE(metadata VARCHAR(200))
INSERT #test VALUES('StudentID:1234,StudentName:TestName,StudentNickName:TestNName,StudentLevel:5')
INSERT #test VALUES('StudentID:1235,StudentName:TestName1,StudentNickName:TestNName1,StudentLevel:6')
INSERT #test VALUES('StudentID:1236,StudentName:TestName2,StudentNickName:TestNName2,StudentLevel:2')
INSERT #test VALUES('')
SELECT split.s.value('.','VARCHAR(100)') as colname FROM
(
SELECT CAST('<s>' + REPLACE(metadata,',','</s><s>') + '</s>' AS XML) col FROM #test
) AS t CROSS APPLY col.nodes('/s') AS split(s)
WHERE split.s.value('.','VARCHAR(100)') LIKE '%StudentNickName%'

select items where column NOT IN itemList

QuickExplain :My elementList is [1, 2, 3, 4] and if 3, 4 is not present in table I want 3, 4.
PS. If you use "NOT IN" this returns you values from table But I want only elements from elementList I queried.
You can use a temporary table:
create table #elements (name varchar(50))
insert into #elements (name) values ('1')
insert into #elements (name) values ('2')
insert into #elements (name) values ('3')
insert into #elements (name) values ('4')
select name
from #elements
where name not in (select col1 from tab);
drop table #elements
Try doing the reverse whatever you are doing. If you want only elements from element list then try this
select elements from elementList where col1 not in (select col1 from table)
A bit verbose but solves the purpose cleanly
select * from
(select 'item1' as items UNION
select 'item2' as items UNION
.
.
.
select 'itemN' as items ) as notFoundItemList where items NOT IN
(
Select ITEM from table WHERE AND itemName in
)