- Showcasing PIVOT
- Open JSON
- JSON TO XML
Last active
June 14, 2023 12:24
-
-
Save vibs2006/3c4295be014845de61ec6a3835688c9e to your computer and use it in GitHub Desktop.
SQL Server Use Case Examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--Converting JSON data to XML using a T-SQL function | |
CREATE FUNCTION dbo.fn_parse_json2xml( | |
@json varchar(max) | |
) | |
RETURNS xml | |
AS | |
BEGIN; | |
DECLARE @output varchar(max), @key varchar(max), @value varchar(max), | |
@recursion_counter int, @offset int, @nested bit, @array bit, | |
@tab char(1)=CHAR(9), @cr char(1)=CHAR(13), @lf char(1)=CHAR(10); | |
--- Clean up the JSON syntax by removing line breaks and tabs and | |
--- trimming the results of leading and trailing spaces: | |
SET @json=LTRIM(RTRIM( | |
REPLACE(REPLACE(REPLACE(@json, @cr, ''), @lf, ''), @tab, ''))); | |
--- Sanity check: If this is not valid JSON syntax, exit here. | |
IF (LEFT(@json, 1)!='{' OR RIGHT(@json, 1)!='}') | |
RETURN ''; | |
--- Because the first and last characters will, by definition, be | |
--- curly brackets, we can remove them here, and trim the result. | |
SET @json=LTRIM(RTRIM(SUBSTRING(@json, 2, LEN(@json)-2))); | |
SELECT @output=''; | |
WHILE (@json!='') BEGIN; | |
--- Look for the first key which should start with a quote. | |
IF (LEFT(@json, 1)!='"') | |
RETURN 'Expected quote (start of key name). Found "'+ | |
LEFT(@json, 1)+'"'; | |
--- .. and end with the next quote (that isn't escaped with | |
--- and backslash). | |
SET @key=SUBSTRING(@json, 2, | |
PATINDEX('%[^\\]"%', SUBSTRING(@json, 2, LEN(@json))+' "')); | |
--- Truncate @json with the length of the key. | |
SET @json=LTRIM(SUBSTRING(@json, LEN(@key)+3, LEN(@json))); | |
--- The next character should be a colon. | |
IF (LEFT(@json, 1)!=':') | |
RETURN 'Expected ":" after key name, found "'+ | |
LEFT(@json, 1)+'"!'; | |
--- Truncate @json to skip past the colon: | |
SET @json=LTRIM(SUBSTRING(@json, 2, LEN(@json))); | |
--- If the next character is an angle bracket, this is an array. | |
IF (LEFT(@json, 1)='[') | |
SELECT @array=1, @json=LTRIM(SUBSTRING(@json, 2, LEN(@json))); | |
IF (@array IS NULL) SET @array=0; | |
WHILE (@array IS NOT NULL) BEGIN; | |
SELECT @value=NULL, @nested=0; | |
--- The first character of the remainder of @json indicates | |
--- what type of value this is. | |
--- Set @value, depending on what type of value we're looking at: | |
--- | |
--- 1. A new JSON object: | |
--- To be sent recursively back into the parser: | |
IF (@value IS NULL AND LEFT(@json, 1)='{') BEGIN; | |
SELECT @recursion_counter=1, @offset=1; | |
WHILE (@recursion_counter!=0 AND @offset<LEN(@json)) BEGIN; | |
SET @offset=@offset+ | |
PATINDEX('%[{}]%', SUBSTRING(@json, @offset+1, | |
LEN(@json))); | |
SET @recursion_counter=@recursion_counter+ | |
(CASE SUBSTRING(@json, @offset, 1) | |
WHEN '{' THEN 1 | |
WHEN '}' THEN -1 END); | |
END; | |
SET @value=CAST( | |
dbo.fn_parse_json2xml(LEFT(@json, @offset)) | |
AS varchar(max)); | |
SET @json=SUBSTRING(@json, @offset+1, LEN(@json)); | |
SET @nested=1; | |
END | |
--- 2a. Blank text (quoted) | |
IF (@value IS NULL AND LEFT(@json, 2)='""') | |
SELECT @value='', @json=LTRIM(SUBSTRING(@json, 3, | |
LEN(@json))); | |
--- 2b. Other text (quoted, but not blank) | |
IF (@value IS NULL AND LEFT(@json, 1)='"') BEGIN; | |
SET @value=SUBSTRING(@json, 2, | |
PATINDEX('%[^\\]"%', | |
SUBSTRING(@json, 2, LEN(@json))+' "')); | |
SET @json=LTRIM( | |
SUBSTRING(@json, LEN(@value)+3, LEN(@json))); | |
END; | |
--- 3. Blank (not quoted) | |
IF (@value IS NULL AND LEFT(@json, 1)=',') | |
SET @value=''; | |
--- 4. Or unescaped numbers or text. | |
IF (@value IS NULL) BEGIN; | |
SET @value=LEFT(@json, | |
PATINDEX('%[,}]%', REPLACE(@json, ']', '}')+'}')-1); | |
SET @json=SUBSTRING(@json, LEN(@value)+1, LEN(@json)); | |
END; | |
--- Append @key and @value to @output: | |
SET @output=@output+@lf+@cr+ | |
REPLICATE(@tab, @@NESTLEVEL-1)+ | |
'<'+@key+'>'+ | |
ISNULL(REPLACE( | |
REPLACE(@value, '\"', '"'), '\\', '\'), '')+ | |
(CASE WHEN @nested=1 | |
THEN @lf+@cr+REPLICATE(@tab, @@NESTLEVEL-1) | |
ELSE '' | |
END)+ | |
'</'+@key+'>'; | |
--- And again, error checks: | |
--- | |
--- 1. If these are multiple values, the next character | |
--- should be a comma: | |
IF (@array=0 AND @json!='' AND LEFT(@json, 1)!=',') | |
RETURN @output+'Expected "," after value, found "'+ | |
LEFT(@json, 1)+'"!'; | |
--- 2. .. or, if this is an array, the next character | |
--- should be a comma or a closing angle bracket: | |
IF (@array=1 AND LEFT(@json, 1) NOT IN (',', ']')) | |
RETURN @output+'In array, expected "]" or "," after '+ | |
'value, found "'+LEFT(@json, 1)+'"!'; | |
--- If this is where the array is closed (i.e. if it's a | |
--- closing angle bracket).. | |
IF (@array=1 AND LEFT(@json, 1)=']') BEGIN; | |
SET @array=NULL; | |
SET @json=LTRIM(SUBSTRING(@json, 2, LEN(@json))); | |
--- After a closed array, there should be a comma: | |
IF (LEFT(@json, 1) NOT IN ('', ',')) BEGIN | |
RETURN 'Closed array, expected ","!'; | |
END; | |
END; | |
SET @json=LTRIM(SUBSTRING(@json, 2, LEN(@json)+1)); | |
IF (@array=0) SET @array=NULL; | |
END; | |
END; | |
--- Return the output: | |
RETURN CAST(@output AS xml); | |
END; | |
--And here’s how to test the query: | |
DECLARE @json varchar(max); | |
SET @json='{ | |
"Person": { | |
"firstName": "John", | |
"lastName": "Smith", | |
"age": [25, 26, 27], | |
"Address": { | |
"streetAddress":"21, 2nd Street", | |
"city" :"New York", | |
"state":"NY", | |
"postalCode":"10021" | |
}, | |
"PhoneNumbers": { | |
"home":"212 555-1234", | |
"fax":"646 555-4567" | |
} | |
} | |
}'; | |
SELECT dbo.fn_parse_json2xml(@json); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare @json varchar(max) = '[ | |
{ | |
"InvoiceNumber": 3333428, | |
"PaidAmount": 10.0, | |
"Bank": "Bank Name 1", | |
"PaymentReference": "PaymentReference 1" | |
}, | |
{ | |
"InvoiceNumber": 2457759, | |
"PaidAmount": 15.0, | |
"Bank": "Bank Name 2", | |
"PaymentReference": "PaymentReference 2" | |
} | |
]'; | |
SELECT * FROM OPENJSON(@json) | |
WITH (InvoiceNumber BIGINT, | |
PaidAmount DECIMAL(18,2), | |
Bank VARCHAR(255), | |
PaymentReference VARCHAR(512) | |
) as Invoices |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare @countries nvarchar(max) = ''; | |
select @countries = @countries + QUOTENAME(CountryName) + ',' from tblCountry | |
set @countries = LEFT(@countries, len(@countries)-1) | |
declare @sql nvarchar(max) = N'select top 10 * from (select c.CountryName, YEAR(f.FilmReleaseDate) as [Year] from tblCountry c inner join tblFilm f on c.CountryID = f.FilmCountryID | |
) as pivotData | |
pivot ( | |
count(CountryName) | |
For [CountryName] | |
in (' + @countries + N')) as pivottable where [United States] != 0 and [United Kingdom] != 0' | |
exec sp_executesql @sql |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment