I would like to retrieve values from JSON column.
There are my data :
I try to get firstName, lastName, "home" and "work" from shippingAddress JSON column.
So I use this query :
SELECT id, lastName, firstName, homeAddress, workAddress
FROM dbo.person
CROSS APPLY OPENJSON (shippingAddress ,'$') WITH (
homeAddress nvarchar(4000) '$.home', workAddress nvarchar(4000)
'$.work' )
And the result is :
but I would like to have this result :
Someone can help me ?
Ok I found the solution :
SELECT lastName, firstName, homeAddress =
JSON_VALUE(shippingAddress, '$[0].home'), workAddress =
JSON_VALUE(shippingAddress, '$[1].work') FROM dbo.person pp
Related
I have the following tables (pseudo names below) in SQL which I need to use to produce some dynamic JSON out from :
HeaderTable
RequestID int
RequestType varchar(50)
Sample Data
1 : User Name Change
2 : User Name Change
ValuesTable
RequestID int
Alias varchar(50)
FieldValue varchar(50)
Sample Data
1 : MobileNo : 07777777777
1 : Name : Fred Bloggs
2 : MobileNo : 07888888888
2 : Name : John Smith
The JSON I need to end up with is as follows :
[
{
"request_type":"User Name Change",
"request_details":[
{
"MobileNo":"07777777777",
"Name":"Fred Bloggs"
},
{
"MobileNo":"07888888888",
"Name":"John Smith"
}
]
}
]
So I effectively need to pass my alias value as the key name in the JSON.
My code so far is as follows but I assume I might need some sort of dynamic SQL?
SELECT hdr.RequestType AS request_type
, (
SELECT vals.FieldValue AS [request_details.value]
FROM ValuesTable vals
WHERE vals.RequestID = hdr.[RequestID]
FOR JSON PATH
) request_details
FROM HeaderTable hdr
FOR JSON PATH
I'm not sure if any of the other SQL JSON function might be useful here or if I need to somehow churn out some dynamic SQL as my only hope?
I don't think you can build the required JSON directly (usinf FOR JSON), but you may try to build one part of the JSON output using basic string concatenation and aggregation. Note, that starting for SQL Server 2016, you need to use FOR XML PATH for aggregation:
Data:
SELECT *
INTO HeaderTable
FROM (VALUES
(1, 'User Name Change')
) v (RequestID, RequestType)
SELECT *
INTO ValuesTable
FROM (VALUES
(1, 'MobileNo', '07777777777'),
(1, 'Name', 'Fred Bloggs'),
(1, 'Address', 'Full address'),
(2, 'MobileNo', '07888888888'),
(2, 'Name', 'John Smith')
) v (RequestID, Alias, FieldValue)
Statement for SQL Server 2017:
SELECT
hdr.RequestType AS request_type,
JSON_QUERY((
SELECT CONCAT(
'[{',
STRING_AGG(
CONCAT(
'"',
STRING_ESCAPE(vals.Alias, 'json'),
'":"',
STRING_ESCAPE(vals.FieldValue, 'json'), '"'
),
','
),
'}]'
)
FROM ValuesTable vals
WHERE vals.RequestID = hdr.[RequestID]
)) AS request_details
FROM HeaderTable hdr
FOR JSON PATH
Statement for SQL Server 2016:
SELECT
hdr.RequestType AS request_type,
JSON_QUERY(CONCAT(
'[{',
STUFF(
(
SELECT CONCAT(',"', vals.Alias, '":"', vals.FieldValue, '"')
FROM ValuesTable vals
WHERE vals.RequestID = hdr.[RequestID]
FOR XML PATH(''), TYPE
).value('.', 'varchar(max)'),
1, 1, ''
),
'}]'
)) AS request_details
FROM HeaderTable hdr
FOR JSON PATH
Result:
[
{
"request_type":"User Name Change",
"request_details":[
{
"MobileNo":"07777777777",
"Name":"Fred Bloggs",
"Address":"Full address"
}
]
}
]
database noob so please bear with me. Writing in Oracle MySql.
I have a block of code which notably is meant to add rows to DWCUST but change invalid gender values coming from a2custbris to valid ones by comparing them to the genderspelling table. I wrote the select code in the brackets to do this and it works. However, certain gender values are null in a2custbris, I want these to be written as 'U' in DWCUST. So how can I do both?
Here's the code:
INSERT INTO DWCUST (DWCUSTID, DWSOURCEIDBRIS, DWSOURCEIDMELB, FIRSTNAME, SURNAME, GENDER, PHONE, POSTCODE, CITY, STATE, CUSTCATNAME)
SELECT dwcustSeq.nextval, cb.custid, Null, cb.fname, cb.sname, (select trim(gs.NEW_VALUE) FROM genderspelling gs WHERE upper(gs.INVALID_VALUE) = upper(cb.GENDER)), cb.phone, cb.postcode, cb.city, cb.state, cc.custcatname
FROM a2custbris cb
NATURAL JOIN a2custcategory cc
WHERE cb.rowid IN (SELECT source_rowid FROM A2ERROREVENT where filterid = 7);
Any help is creating appreciated!
Use a CASE expression:
INSERT INTO DWCUST (DWCUSTID, DWSOURCEIDBRIS, DWSOURCEIDMELB, FIRSTNAME, SURNAME,
GENDER, PHONE, POSTCODE, CITY, STATE, CUSTCATNAME)
SELECT
dwcustSeq.nextval, cb.custid, Null, cb.fname, cb.sname,
CASE WHEN cb.gender IS NULL THEN 'U'
ELSE (select trim(gs.NEW_VALUE) FROM genderspelling gs
WHERE upper(gs.INVALID_VALUE) = upper(cb.GENDER))
END,
cb.phone, cb.postcode, cb.city, cb.state, cc.custcatname
FROM a2custbris cb
NATURAL JOIN a2custcategory cc
WHERE cb.rowid IN (SELECT source_rowid FROM A2ERROREVENT where filterid = 7);
If you want 'U' for every value that has no match in genderspelling, then use COALESCE instead:
INSERT INTO DWCUST (DWCUSTID, DWSOURCEIDBRIS, DWSOURCEIDMELB, FIRSTNAME, SURNAME,
GENDER, PHONE, POSTCODE, CITY, STATE, CUSTCATNAME)
SELECT
dwcustSeq.nextval, cb.custid, Null, cb.fname, cb.sname,
COALESCE(
(select trim(gs.NEW_VALUE) FROM genderspelling gs
WHERE upper(gs.INVALID_VALUE) = upper(cb.GENDER))
, 'U'),
cb.phone, cb.postcode, cb.city, cb.state, cc.custcatname
FROM a2custbris cb
NATURAL JOIN a2custcategory cc
WHERE cb.rowid IN (SELECT source_rowid FROM A2ERROREVENT where filterid = 7);
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=95c4db0d481492956af1a2f566359a38
I'm writing a new query for a project, and trying to format the JSON string so that it will give me an array instead of an object in MoreInfo.
I've been able to mess around with the formatting, but can't seem to shake off the Score column label. What's the best way to do this?
SELECT TOP (1)
contacts.PhoneNumber,
contacts.ContactName,
MoreInfo.Score
FROM (SELECT
PrimaryPhone as PhoneNumber,
FirstName + ' ' + LastName as ContactName,
callList.Call_Identity
FROM CallList callList
INNER JOIN dbo.Contacts a
ON callList.Call_IDENTITY = a.Call_IDENTITY
) contacts
INNER JOIN
(
SELECT CAST(Score as varchar) as Score, Call_Identity
FROM dbo.Contacts contact
) MoreInfo on MoreInfo.Call_Identity = contacts.Call_Identity
FOR JSON AUTO;
Current results:
[
{
"PhoneNumber":"3172222222",
"ContactName":"Peyton Manning",
"MoreInfo":[
{
"Score":"0.1",
}
]
}
]
I'm trying to get:
[
{
"PhoneNumber":"3172222222",
"ContactName":"Peyton Manning",
"MoreInfo":["0.1"]
}
]
It seems like you're hugely over complicating your query:
SELECT c.PrimaryPhone AS PhoneNumber,
c.FirstName + ' ' + c.LastName AS ContactName,
c.Score AS MoreInfo
FROM dbo.callList cL --Why is this even here, it's never referenced
JOIN Contacts C ON cL.Call_IDENTITY = C.Call_Identity
FOR JSON AUTO;
This returns the below:
[
{
"PhoneNumber":"3172222222",
"ContactName":"Peyton Manning",
"MoreInfo":0.10
}
]
This is quite a hack but I think it would technically work for you. Basically you just separate out the array that you're looking for using a string concatenation and then use JSON_Query to have the main query treat it as a JSON value so that it doesn't try to convert it to JSON again.
I did the best I could with the example, it's a little difficult to understand the structure of your data.
WITH contacts
AS (SELECT Call_Identity = 1, PhoneNumber = '3172222222', ContactName = 'Peyton Manning', Score = 0.1)
SELECT a.Call_Identity,
a.PhoneNumber,
a.ContactName,
MoreInfo = JSON_QUERY((
SELECT Score = '[' + STRING_AGG( '"' + CAST(Score AS VARCHAR) + '"',',') + ']'
FROM contacts x
WHERE x.Call_Identity = a.Call_Identity
GROUP BY Call_Identity
) )
FROM contacts a
FOR JSON AUTO
Given this query:-
SELECT id as id,
attributes->>'name' as file_name,
status
from workflow.events
where schema='customer'
and type='FILE_UPLOAD'
id,file_name, status
1,name,status
2,name2,status2
I want to output this structure:-
{
"1" :{"id" :"1", "file_name" : "name", "status" : "status1"},
"2" :{"id" :"2", "file_name" : "name2","status" : "status2"}
}
I can do it at the moment using string functions but this seems messy and inefficient. CAn it be done using the native postgresql json functions?
If you want to get two records with json, use row_to_json() function:
with cte as (
select
id as id,
attributes->>'name' as file_name,
status
from workflow.events
where schema='customer' and type='FILE_UPLOAD'
)
select row_to_json(c) from cte as c
output:
{"id":1,"file_name":"name","status":"status"}
{"id":2,"file_name":"name2","status":"status2"}
If you want to get json array:
with cte as (
select
id as id,
attributes->>'name' as file_name,
status
from workflow.events
where schema='customer' and type='FILE_UPLOAD'
)
select json_agg(c) from cte as c
output:
[{"id":1,"file_name":"name","status":"status"},
{"id":2,"file_name":"name2","status":"status2"}]
But for you desired output, I can only suggest string transformation:
with cte as (
select
id::text as id,
file_name,
status
from workflow.events
where schema='customer' and type='FILE_UPLOAD'
)
select ('{' || string_agg('"' || id || '":' || row_to_json(c), ',') || '}')::json from cte as c
sql fiddle demo
I have a requirement that i want to search for data in xml data type, from the front end i will get firstname,lastname,dob,email all the fields are not mandatory some fields will come as empty or null i want to search according to that if i will get firstname as 'test' and lastname i will get as empty or null
If it is a varchar datatype then i can create query as
FirstName= ISNULL(#firstname, FirstName) or COALESCE(#firstname, FirstName, '') = '')
but in XML doc how can i use this type of query.
xmlDoc.value('(/personalDetails/firstname)[1]','varchar(100)')
Thanks
In SQLServer 2008, I would write something like :
select
xmlDoc.value('(personalDetails/firstname/text())[1]','varchar(100)') as firstname
from
myTable
where
not xmlDoc is null
and xmlDoc.exist('personalDetails/firstname[.!='''']')>0
You can also do a CASE WHEN ... ELSE ... END if you want to return NULL for non existing values
I think you can achieve this using common table expression. PFB the sample code-
DECLARE #XMLData XML
SET #XMLData ='
<STUDENTS>
<STUDENT>
<StudentID>1</StudentID>
<Name>John Smith</Name>
<Marks>200</Marks>
</STUDENT>
<STUDENT>
<StudentID>2</StudentID>
<Name>Mark Johnson</Name>
<Marks>300</Marks>
</STUDENT>
<STUDENT>
<StudentID>3</StudentID>
<Name></Name>
<Marks>400</Marks>
</STUDENT>
</STUDENTS>'
;with cte as(
SELECT StudentID = Node.Data.value('(StudentID)[1]', 'INT')
, [Name] = Node.Data.value('(Name)[1]', 'VARCHAR(MAX)')
, [Marks] = Node.Data.value('(Marks)[1]', 'INT')
FROM #XMLData.nodes('/STUDENTS/STUDENT') Node(Data)
)
Select * from cte where Name=''