sort the json array in postgresql - json
create table sort(authorized json);
insert into sort values('{"name":"Authorized","states":[{"state_code":"CT","state_name":"Connecticut","is_checked":false},{"state_code":"NJ","state_name":"New Jersey","is_checked":false},{"state_code":"SC","state_name":"South Carolina","is_checked":false},{"state_code":"FL","state_name":"Florida","is_checked":false},{"state_code":"MT","state_name":"Montana","is_checked":false},{"state_code":"GA","state_name":"Georgia","is_checked":false},
{"state_code":"IA","state_name":"Iowa","is_checked":false},{"state_code":"AR","state_name":"Arkansas","is_checked":false},{"state_code":"UT","state_name":"Utah","is_checked":false},{"state_code":"ID","state_name":"Idaho","is_checked":false},{"state_code":"IL","state_name":"Illinois","is_checked":false},{"state_code":"IN","state_name":"Indiana","is_checked":false},{"state_code":"MA","state_name":"Massachusetts","is_checked":false},{"state_code":"MI","state_name":"Michigan","is_checked":false},{"state_code":"MS","state_name":"Mississippi","is_checked":false},{"state_code":"NM","state_name":"New Mexico","is_checked":false},{"state_code":"NV","state_name":"Nevada","is_checked":false},{"state_code":"RI","state_name":"Rhode Island","is_checked":false},{"state_code":"SD","state_name":"South Dakota","is_checked":false},{"state_code":"UT","state_name":"Utah","is_checked":false},{"state_code":"WV","state_name":"West Virginia","is_checked":false},{"state_code":"SD","state_name":"South Dakota","is_checked":false},
{"state_code":"WV","state_name":"West Virginia","is_checked":false}]}')
I want that this json sort according to state_code after update it looks like
{"name":"Authorized","states":[{"state_code":"AR","state_name":"Arkansas","is_checked":false},{"state_code":"CT","state_name":"Connecticut","is_checked":false},{"state_code":"FL","state_name":"Florida","is_checked":false},{"state_code":"GA","state_name":"Georgia","is_checked":false},
{"state_code":"IA","state_name":"Iowa","is_checked":false},{"state_code":"ID","state_name":"Idaho","is_checked":false},{"state_code":"IL","state_name":"Illinois","is_checked":false},{"state_code":"IN","state_name":"Indiana","is_checked":false},{"state_code":"MA","state_name":"Massachusetts","is_checked":false},{"state_code":"MI","state_name":"Michigan","is_checked":false},{"state_code":"MS","state_name":"Mississippi","is_checked":false},{"state_code":"MT","state_name":"Montana","is_checked":false},{"state_code":"NJ","state_name":"New Jersey","is_checked":false},{"state_code":"NM","state_name":"New Mexico","is_checked":false},{"state_code":"NV","state_name":"Nevada","is_checked":false},{"state_code":"RI","state_name":"Rhode Island","is_checked":false},{"state_code":"SC","state_name":"South Carolina","is_checked":false},{"state_code":"SD","state_name":"South Dakota","is_checked":false},{"state_code":"UT","state_name":"Utah","is_checked":false},{"state_code":"WV","state_name":"West Virginia","is_checked":false},{"state_code":"SD","state_name":"South Dakota","is_checked":false},{"state_code":"UT","state_name":"Utah","is_checked":false},
{"state_code":"WV","state_name":"West Virginia","is_checked":false}]}
try this:
select substr(column_name, position ('state_code":"' in column_name)+13,4) as stateCode
from table_name
order by stateCode asc/desc
note:the value 13 represents the lenght of field (state_code":) and 4 represents value of field ("AR")
might need to tweak a little according to you table and column. The select part would select your desired element then you only have to order it by asc or desc.
You can get the results ordered when retrieving the data through sorting within the subquery while extracting the concerned array(states) as a seperate column, and then aggregating the individual objects of the array back while adhering name element of the object such as
SELECT JSON_AGG(
JSON_BUILD_OBJECT( 'name', name, 'states', states)
) AS authorized
FROM
(
SELECT authorized->'name' AS name, j.states
FROM sort,
JSON_ARRAY_ELEMENTS(authorized->'states') AS j(states)
ORDER BY j.states->>'state_code' ) AS ns
Demo
Related
How to efficiently check a JSON array for values in T-SQL
I want to find multiple rows where a JSON array contains a specific value or values. Sometimes all match items will need to match (ANDs), sometimes only some (ORs) and sometimes a combination of both (ANDs and ORs). This is in Microsoft SQL Server 2017. I've tried doing an AS statement in the select but that resulted in the alias created for the subquery not being recognised later on in the subquery. The bellow example works, it just seems innificent and has code duplication. How would I only specify SELECT VALUE FROM OPENJSON(JsonData, '$.categories' once? Or perhaps there is some other way to do this? DECLARE #TestTable TABLE ( Id int, JsonData nvarchar(4000) ); INSERT INTO #TestTable VALUES (1,'{"categories":["one","two"]}'), (2,'{"categories":["one"]}'), (3,'{"categories":["two"]}'), (4,'{"categories":["one","two","three"]}'); SELECT [Id] FROM #TestTable WHERE ISJSON(JsonData) = 1 -- These two lines are the offending parts of code AND 'one' in (SELECT VALUE FROM OPENJSON(JsonData, '$.categories')) AND 'two' in (SELECT VALUE FROM OPENJSON(JsonData, '$.categories')); The table format cannot change, though I can add computed columns - if need be.
Well, I'm not sure if this helps you... It might help to transform the nested array to a derived table to use it as a CTE. Check this out: DECLARE #TestTable TABLE ( Id int, JsonData nvarchar(4000) ); INSERT INTO #TestTable VALUES (1,'{"categories":["one","two"]}'), (2,'{"categories":["one"]}'), (3,'{"categories":["two"]}'), (4,'{"categories":["one","two","three"]}'); --This is the query WITH JsonAsTable AS ( SELECT Id ,JsonData ,cat.* FROM #TestTable tt CROSS APPLY OPENJSON(tt.JsonData,'$.categories') cat ) SELECT * FROM JsonAsTable The approach is very close to the query you formed yourself. The result is a table with one line per array entry. The forme Id is a repeated grouping key, the key is the ordinal position within the array, while the value is one of the words you are searching for. In your query you can use JsonAsTable like you'd use any other table in this place. But - instead of the repeated FROM OPENJSON queries - you will need repeated EXISTS() predicates... A hacky solution might be this: SELECT Id ,JsonData ,REPLACE(REPLACE(REPLACE(JsonData,'{"categories":[','",'),']}',',"'),'","',',') FROM #TestTable This will return all nested array values in one string, separated by a comma. You can query this using a LIKE pattern... You could return this as computed column though...
Insert ID in column with values separated by comma
I have a column that lists all the units ids from a company which are allowed to see a specific document. Like this: And those ids are selected here ('Selecionar todas' mean 'Select All'): The problem is when I add a new Unit, it come unselected and it will be a headache to have to enter in all of the documents that are supposed to show to all units and change it to be selected. Is there a way to insert the new Unit's id into the 'idsunidades' column where there are all the other units selected ? Sorry for the bad English.
To implement a select all option you should use a flag column all_selected(true or false) or you can do it like this: To select the rows where All units are selected should have the longest value of idsunidades, you can select them like this SELECT #maxLength:=LENGTH(idsunidades) ORDER BY LENGTH(idsunidades ) DESC LIMIT 1 You can use CONCAT() to append the new id to the old column data To add the unit 99 to the column idsunidades to all the rows with all units you can do this UPDATE table set idsunidades=CONCAT(idsunidades, ',99') WHERE LENGTH(idsunidades) = (SELECT LENGTH(idsunidades) ORDER BY LENGTH(idsunidades ) DESC LIMIT 1)
data ordering issue in mysql for a particular column
I have a table in which there is column name as mappedcloumnname and fieldname and my fieldcolumn contains address1, address2, city, state, customerid, country and mappedcolumn contanins c1-c20. I wrote a query to sort my data based on mappedcolumn name but the order what am getting is wrong one SELECT * FROM customermetadata WHERE OrgID = in_orgid ORDER BY MappedColumnName;
You can give it a try: SELECT * FROM customermetadata WHERE OrgID = in_orgid ORDER BY CAST(SUBSTRING(MappedColumnName FROM 2) AS UNSIGNED); Note: Here I've extracted the number from the MappedColumnName and sort the records based the extracted numbers. I've created a demo where the table contains only two columns (id and col). col column contains value like c1,c2,.... See demo if you order by col only. See demo if you order by extracting number from col.
If your column MappedColumnName contains value from c1-c20, then it will be treated as String(VarChar) in SQL and data will not be sorted properly.
You should try in this way, select * from customermetadata where OrgID=in_orgid Order By CAST(SUBSTR(MappedColumnName FROM 2 FOR LENGTH(MappedColumnName)) AS UNSIGNED); ; NOTE: A longer number is also a bigger number for numbers of the same length, you can make a textual comparison, because '0' < '1' .... < '9' and it will short Alpha-numeric order.
PostgreSQL dynamically SELECT last json array value
How do I dynamically SELECT the last array value in a JSON type column in PostgreSQL? id: 2927 material_size: [".016 x 1.156","0","1"] I could statically retrieve the last value "1" using: SELECT material_size->>2 AS material_size FROM table_name; However that would always get the second record instead of the last record (if the number of values isn't exactly three).
You can get the length of the JSON array and use that (minus one) as the index: with t1 as (select 2927 id, '[".016 x 1.156","0","1"]'::json material_size) select material_size->>(json_array_length(material_size)-1) from t1; See http://www.postgresql.org/docs/9.4/static/functions-json.html.
You can use negative index to query elements in a JSON value from the end: SELECT material_size->>-1 AS material_size FROM table_name;
I need some help getting MySql to output some results using a subquery
I'm storing a list of numbers inside a table as a varchar(255) and want to use this list in another query's "IN() clause. Here's what I mean: Table Data: CREATE TABLE IF NOT EXISTS `session_data` ( `visible_portf_ids` varchar(255) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `session_data` (`visible_portf_ids`) VALUES ('45,44,658,659,661,45,44,658,659,661') I want to run a query like this to return a list of portfolio's "QUERY #1": SELECT portfolio_hierarchy_id, account_id, name, leaf_node_portf_id FROM portfolio_hierarchy WHERE account_id = 1 AND leaf_node_portf_id IN ( (SELECT visible_portf_ids FROM session_data WHERE username = 'ronedog') ) ORDER BY name ASC The result of the query above returns only 1 row, when there are a total of 3 that should have been returned. If I run the subquery alone like this: (SELECT visible_portf_ids FROM session_data WHERE username = 'ronedog') it will return a list like this: 45,44,658,659,661,45,44,658,659,661 But, when I run Query #1 above, only one row of data, which is associated with the "visible_portf_ids" of "45" is returned. If I replace the subquery with hard coded values like this: SELECT portfolio_hierarchy_id, account_id, name, leaf_node_portf_id FROM portfolio_hierarchy WHERE account_id = 1 AND leaf_node_portf_id IN (45,44,658,659,661,45,44,658,659,661) ORDER BY name ASC then I get all 3 rows I'm expecting. I'm guessing that MySql is returning the list as a string because its stored as a varchar() and so it stops processing after the first "visible_portf_ids" is found, which is "45", but I'm not really sure. Anyone got any ideas how I can fix this? Thanks in advance.
You should think about restructuring your tables storing each value in a new row, instead of concatenating them. Until then, you can use the FIND_IN_SET() function: AND FIND_IN_SET(leaf_node_portf_id, (SELECT visible_portf_ids FROM session_data WHERE username = 'ronedog' LIMIT 1) ) > 0
Unfortunately MySQL does not have a function to split a delimited string. Your IN argument is a single string with the result of your subquery. The reason it works when you hard-code it is that MySQL is parsing the values. I suggest that you redesign your data base to store the visible ports list as separate rows in a separate table. Then you can retrieve them and use them in subqueries like you tried.