I want to get a JSON object formatted similar to this:
{
"username": "USERNAME",
"teamname": "TEAMNAME",
"logs": [
{
"log": {
"log_id": 29,
"person_id": 3,
"activity_id": 3,
"shoe_id": null,
"logdate": "2016-11-29",
"distance": null,
"activitytime": null,
"sleep": null,
"heartrate": null,
"logtitle": null,
"description": null
},
"activity": "Swim",
"comments": {
"comment_id": 1,
"description": "This is a comment",
"person_id": 1,
"log_id": 29
}
}]
}
Currently I have everything formatted correctly except the comments. Here is the SQL query I am using:
SELECT p.username, t.teamname, json_agg(json_build_object('log', l.*, 'comments', c.*, 'activity', a.activity)) as logs
FROM person_tbl p
INNER JOIN log_tbl l ON p.person_id = l.person_id
INNER JOIN activity_tbl a ON l.activity_id = a.activity_id
INNER JOIN comment_tbl c ON c.log_id = l.log_id
INNER JOIN person_team_tbl pt ON p.person_id = pt.person_id
INNER JOIN team_tbl t on t.team_id = pt.team_id
WHERE t.team_id = 5
AND l.logdate > NOW()::date - 7
GROUP BY p.username, t.teamname
ORDER BY p.username
I'm having trouble getting the comments of each log. Right now, it is returning every comment and repeating the logs (they are not associated).
Also, how could I get this query to return the username and teamname when everything else is null (like when there are no logs in the past week)?
Without an SQLfiddle we do not know what your data (and structure) is so it is difficult to answer your question.
For the NULL case - please modify the WHERE clause like this (deliberately not using COALESCE)
WHERE t.team_id = 5 AND (l.logdate IS NULL OR l.logdate > NOW()::date - INTERVAL '7 day')
Related
I want to transform the result from a select with joins into a json object. I mean this query:
select
cm.*,
e.*,
u.*,
from
chat_messages cm,
events e,
users u
where
cm.event_id = e.id
and cm.user_id = u.id
should output this:
{
"id": 1,
"message": "whatever",
"time": "2021-12-02T00:21:10.571848",
"user": {
"id": 35,
"name": "John Smith"
},
"event": {
"id": 19,
"name": "Test event",
"time": "2021-09-22T00:00:00-03:00",
"local": "Planet Earth"
}
}
(there are more fields than these. I'm just making the example simple)
I found a solution this way:
select
json_build_object(
'id', cm.id,
'message', cm.message,
'time', cm.time,
'user', to_json(u.*),
'event', to_json(e.*)
)
from
chat_messages cm,
events e,
users u
where
cm.event_id = e.id
and cm.user_id = u.id
But I think there should be a much better way to do this. Imagine that chat_messages had a lot more fields. It would be lengthy to describe field by field.
What I want is a way to for the query to transform subqueries in json without me describing field by field.
Anyone knows a better way to do this ?
According to, Postgres document you can use the row_to_json function to transfer row to JSON and then append each table rows with an alias to be detected by row_to_json
with cte as (
select
cm.*,
e as event,
u as user
from
chat_messages cm,
events e,
users u
where
cm.event_id = e.id
and cm.user_id = u.id
)
select row_to_json(c) from cte c;
Hello everyone, I have the following query below which contains a sub query:
SELECT g.id, g.name, data.permissions, gp.has_permission
FROM groups g
RIGHT JOIN groups_permissions gp ON gp.group_id = g.id
RIGHT JOIN (SELECT p.id, array_to_json(array_agg(to_json(p.*)))
FROM permissions p
GROUP BY p.id) AS data (id, permissions) ON (gp.permission_id = data.id)
WHERE g.id=1
This query returns the result bellow:
[
{
"id": "7a588463-1780-459a-9646-8f19e9cb6ded",
"name": "Administradores",
"permissions": [
{
"id": "bf9d5ee3-d554-4faa-9cf4-9c60acb79801",
"name": "Criar Grupos",
"slug": "criar-grupos",
"created_at": "2020-12-07T00:50:05.017783",
"updated_at": "2020-12-07T00:50:05.017783"
}
],
"has_permission": true
}
]
I would like to have the has_permission field inside the object in the permissions array.
Could someone help merge that field with the object?
Thank you for now.
Don't you just need to add has_permission to the json subrecord?
SELECT g.id, g.name, data.permissions
FROM groups g
RIGHT JOIN groups_permissions gp ON gp.group_id = g.id
RIGHT JOIN (SELECT p.id, array_to_json(array_agg(to_json(p.*, gp.has_permission)))
FROM permissions p
GROUP BY p.id) AS data (id, permissions) ON (gp.permission_id = data.id)
WHERE g.id=1
Good day Stackoverflow,
I have found myself in a bit of a weird query situation. You see, I have to come up with a stored procedure that returns a data set like so;
[
"TestCase1": {
"SetText": {
"Element":"Username"
"Value":"123456"
},
"SetText": {
"Element":"Username",
"Value":"Admin"
},
"OnClick": {
"Element":"SubmitButton"
},
"Login": {
"Username":"admin",
"Password":"123456"
}
}
]
As you can see the data set is held together by the TestCase1 which is in reference to a Table Column Name. Test.Name
Follow by, the function name holding multiple objects.
Each function has its Keys be the parameter name and the keys values are the parameters values
So in this example, Test Case 1 has 4 actions
SetText("Username", "123456")
SetText("Password", "Admin")
OnClick("SubmitButton")
Login("Admin","123456")
The problem is; the query list below I can't alter it to the way I have the JSON above
SELECT TD.ID, F.[Name] AS [Function], P.[Name] AS [Parameter], E.[Name] AS [Data] FROM [QA].[TestData] TD
LEFT JOIN QA.[Parameter] P ON P.ID = TD.ParameterID
INNER JOIN QA.[Function] F ON F.ID = P.FunctionID
INNER JOIN QA.[XREF_Parameter_Element] XPE ON (P.ParameterTypeID = 1) AND (XPE.ID = TD.DataID)
INNER JOIN QA.[Element] E ON E.ID = XPE.ElementID
UNION ALL
SELECT TD.ID, F.[Name] AS [Function], P.[Name] AS [Parameter], XPV.[Value] AS [Data] FROM [QA].[TestData] TD
LEFT JOIN QA.[Parameter] P ON P.ID = TD.ParameterID
INNER JOIN QA.[Function] F ON F.ID = P.FunctionID
INNER JOIN QA.[XREF_Parameter_Value] XPV ON (P.ParameterTypeID <> 1) AND (XPV.ID = TD.DataID)
ORDER BY TD.ID
FOR JSON PATH, ROOT('TestCase1')
Here is what the query above turns out to be
{
"TestCase1":[
{
"ID":1,
"Function":"SetText",
"Parameter":"Element",
"Data":"Username"
},{
"ID":2,
"Function":"SetText",
"Parameter":"Value",
"Data":"123456"
},{
"ID":3,
"Function":"SetText",
"Parameter":"Element",
"Data":"Username"
},{
"ID":4,
"Function":"SetText",
"Parameter":"Value",
"Data":"Admin"
},{
"ID":5,
"Function":"OnClick",
"Parameter":"Element",
"Data":"SubmitButton"
},{
"ID":6,
"Function":"Login",
"Parameter":"Username",
"Data":"Admin"
},{
"ID":7,
"Function":"Login",
"Parameter":"Password",
"Data":"123456"
}
]
}
Is anyone able to help me out. I am more than willing to share contact information to be more clear. This is just ripping my brain apart.
I'm trying to join two SQL tables with inner join and then return them as JSON from my procedure.
My select statement is:
SELECT
#CustomerAddressesJSON =
(SELECT
Address.AddressID, Address.CustomerID,
Address.AddressTypeID, Address.IsPrimary,
CountryID, StateID, CountyID, DistrictID,
StreetID, StreetNumber, PostalCode,
AdditionalInformation, AddressImageID,
CreatedOn, CreatedBy
FROM
[sCustomerManagement].[tCustomerAddresses] Address
INNER JOIN
[sCustomerManagement].[tAddresses] AddressDetails ON Address.AddressID = AddressDetails.AddressID
WHERE
CustomerID = #CustomerID
FOR JSON AUTO)
and the result is like this:
"customerAddressesJSON": "[ {
"AddressID": 1,
"CustomerID": 1,
"AddressTypeID": "T",
"IsPrimary": true,
"AddressDetails": [
{
"CountryID": 1,
"StateID": 1,
"CountyID": 1,
"DistrictID": 1,
"StreetID": 1,
"StreetNumber": "125",
"PostalCode": "1000",
"AdditionalInformation": "Metro Sofia",
"CreatedOn": "2017-10-24T11:46:20.1933333",
"CreatedBy": 24
}
]
}, {
"AddressID": 2,
"CustomerID": 1,
"AddressTypeID": "T",
"IsPrimary": true,
"AddressDetails": [
{
"CountryID": 1,
"StateID": 1,
"CountyID": 1,
"DistrictID": 1,
"StreetID": 1,
"StreetNumber": "125",
"PostalCode": "1000",
"AdditionalInformation": "Metro Sofia",
"CreatedOn": "2017-10-24T11:46:20.1933333",
"CreatedBy": 24
}
]
}
The problem is that I don't want the information in the array AddressDetails to be nested. Is it possible the information there to be outside, so I can receive 2 flat objects, without nested information ?
Thanks
Consider using the PATH mode with dot syntax and map all fields to Address as discussed in docs.
SELECT
#CustomerAddressesJSON =
(SELECT
a.AddressID AS 'Address.AddressID', a.CustomerID AS 'Address.CustomerID',
a.AddressTypeID AS 'Address.AddressTypeID', a,IsPrimary AS 'Address.IsPrimary',
d.CountryID AS 'Address.CountryID', d.StateID AS 'Address.StateID',
d.CountyID AS 'Address.CountyID', d.DistrictID AS 'Address.DistrictID',
d.StreetID As 'Address.StreetID', d.StreetNumber AS 'Address.StreetNumber',
d.PostalCode AS 'Address.PostalCode',
d.AdditionalInformation AS 'Address.AdditionalInformation',
d.AddressImageID AS 'Address.AddressImageID',
d.CreatedOn AS 'Address.CreatedOn', d.CreatedBy AS 'Address.CreatedBy'
FROM
[sCustomerManagement].[tCustomerAddresses] a
INNER JOIN
[sCustomerManagement].[tAddresses] d ON a.AddressID = d.AddressID
WHERE
a.CustomerID = #CustomerID
FOR JSON PATH)
Alternatively, use a derived table:
SELECT
#CustomerAddressesJSON =
(SELECT m.*
FROM
(SELECT a.AddressID, a.CustomerID, a.AddressTypeID, a,IsPrimary,
d.CountryID, d.StateID, d.CountyID, d.DistrictID,
d.StreetID, d.StreetNumber, d.PostalCode,
d.AdditionalInformation, d.AddressImageID,
d.CreatedOn, d.CreatedBy
FROM
[sCustomerManagement].[tCustomerAddresses] a
INNER JOIN
[sCustomerManagement].[tAddresses] d ON a.AddressID = d.AddressID
WHERE
a.CustomerID = #CustomerID
) AS m
FOR JSON AUTO)
I've tried both right and inner join, either I end up with an extra record or not record at all. Please suggest what to fix in this query.
Table structure
Event -> Day -> Session
session_attendee
SELECT session.id,
(SELECT count(*) from event e INNER JOIN day AS d ON e.id = d.event_id INNER JOIN session AS s ON d.id = s.day_id WHERE e.id = event.id AND d.id = day.id) AS total,
day.date, session.name, session.start, session.end, session.room,
(SELECT COUNT(distinct attendee_id) FROM session s LEFT JOIN session_attendee AS sa ON s.id = sa.session_id WHERE s.id = session.id) AS attendees
FROM event
LEFT JOIN day ON event.id = day.event_id
LEFT JOIN session ON day.id = session.day_id
LEFT JOIN session_attendee ON session.id = session_attendee.session_id
WHERE event.id = 12
GROUP BY session.id
ORDER BY day.date, session.start, event.name;
Resultset
[
{
"id": 9,
"total": 1,
"date": "2015-05-12T04:00:00.000Z",
"name": "test",
"start": "00:55:00",
"end": "00:55:00",
"room": "abc",
"attendees": 0
},
{
"id": null,
"total": 0,
"date": "2015-05-13T04:00:00.000Z",
"name": null,
"start": null,
"end": null,
"room": null,
"attendees": 0
}
]
Just try it on postgresql, you sql query will fail, because it's wrong.
You are trying to select fields without an aggregate function and why do you not have a GROUP BY?
But the main reason why it is an incorrect query, is that you must change it to something like this:
WHERE session.id in (
SELECT
session.id
FROM
event
LEFT JOIN
day ON event.id = day.event_id
LEFT JOIN
session ON day.id = session.day_id
WHERE
event.id = 12