Separate single record into two rows by column names - mysql

I want to separate a single record into 2 records by their column names.
Consider only a single record for now.
Currently what I get using simple select query:
{ "id" : "1", "route_name" : "6", "start_up" : "Mumbai", "destination_up" : "Delhi", "start_down" : "Delhi", "destination_down" : "Mumbai" }
What I actually need:
{ "id" : "1", "route_name" : "6", "start_up" : "Mumbai", "destination_up" : "Delhi" }, { "id" : "1", "route_name" : "6", "start_down" : "Delhi", "destination_down" : "Mumbai" }
How can I achieve this using a single query?

you can use an union
select id, route_name, start_up, destination_up
from my_table
where id ='1'
union
select id, route_name, start_down, destination_down
from my_table
where id ='1'

Related

How to update entire JSON object in JSONB postgres column except 1 field

for example I have a table:
CREATE TABLE fruit(id bigint, data jsonb);
and a row for example is:
1,
{
"type": "pinapple",
"store1": {
"first_added": "<some timestamp>",
"price": "10",
"store_id": "1",
"comments": "some comments..."
},
"store2": {
"first_added": "<some timestamp>",
"price": "11",
"store_id": "2",
"comments": "some comments..."
},
.... more stores
}
In case of update I have the fruit id and store data :
1,
"store1": {
"price": "12",
"store_id": "1",
"comments": "some comments...V2"
}
I want to update entire store object in fruit entry (for store1), except the first_added field.
Any idea how I can accomplish it via JSONB operators or functions?
Thanks
You can use
UPDATE fruit
SET data = data || jsonb_set($1::jsonb, '{store1,first_added}', data#>'{store1,first_added}')
WHERE id = 1;
(online demo)
where the parameter $1 is set to the value {"store1": {"price": "12", "store_id": "1", "comments": "some comments...V2"}}.
Or if you need the key to be dynamic, use
UPDATE fruit
SET data = jsonb_set(data, ARRAY[$2::text], jsonb_set($1::jsonb, '{first_added}', data->$2->'first_added'))
WHERE id = 1;
(online demo)
You can use the jsonb_set function to change the desired element, then use the jsonb_build_object function to create a new dataset, then concatenate the data with the || operator to keep the rest of the data(first_added,...)
update table1
set data = jsonb_set(data, '{store1}', jsonb_build_object('first_added', data->'store1'->'first_added', 'price', 12, 'store_id', 1, 'comments', 'some comments...V2'))
where id = 1;
Demo in DBfiddle

Get specific data from MYSQL using PHP

I have two tables as follows
user table
user_id
name
1
zia
2
john
3
raza
subject table
data_id
user_id
subject
1
1
Math
2
1
Chem
3
1
Bio
4
2
Math
5
2
Phy
when I am querying data i am getting results like this:
[
{
"user_id": "1",
"name": "zia",
"subject": [
"Math",
"Chem",
"Bio"
]
},
{
"user_id": "2",
"name": "john",
"subject": [
"Math",
"Phy"
]
},
]
My query is as follows
SELECT
users.user_id,
users.name,
GROUP_CONCAT(subjects.subject) sub
FROM
`users`
INNER JOIN subjects ON users.user_id = subjects.user_id
GROUP BY
subjects.user_id;
but actually I want to get data in following way:
the resuluts shown above are in such a way that if an entry from user table does not have coresponding enteries in subject table even then we must have user name and user id in our rsults as follows
[
{
"user_id": "1",
"name": "zia",
"subject": [
"Math",
"Chem",
"Bio"
]
},
{
"user_id": "2",
"name": "john",
"subject": [
"Math",
"Phy"
]
},
{
"user_id": "3",
"name": "Raza",
}
]
Here as you see that we have data in such a way that all the enteries from user table are shown alog with subject enteries from subject table if they match otherwise every user table entery is showing up with no affect.
*PLease help me in solving this issue **
You probably need to use LEFT JOIN instead of INNER JOIN, because you want to retrieve user without subject too

Delete value from nested json - postgres

I have the json block modeled below. I want to selectively delete individual blocks from my_items based on the id which is AAA and BBB in my sample. ie if I tried to delete the AAA block under my_items I would want tojust delete the {"id" : "AAA"} but if wanted to delete the BBB block it would delete the larger {"name" : "TestRZ", "id" : "BBB", "description" : ""} block.
I know I can use the #- to remove whole blocks like SELECT '{sample_json}'::jsonb #- '{my_items}' would purge out the whole my_items block. But I dont know how to use this to conditionally delete children under a parent block of json. I have also used code similar to this example to append data inside a nested structure by reading in the node of the nested structure cat-ing new data to it and rewriting it. UPDATE data SET value= jsonb_set(value, '{my_items}', value->'items' || (:'json_to_adds'), true) where id='testnofeed'.
But I dont know how to apply either of these methods to: 1)Delete data in nested structure using #- or 2)Do the same using `jsonb_set. Anyone have any guidance for how to do this using either of these(or another method).
{
"urlName" : "testurl",
"countryside" : "",
"description" : "",
"my_items" : [
{
"id" : "AAA"
},
{
"name" : "TestRZ",
"id" : "BBB",
"description" : ""
},
],
"name" : "TheName"
}
Data is stored in value jsonb. when I update I will be able to pass in a unique kind so that it only updates this json in one row in db.
-- Table Definition
CREATE TABLE "public"."data" (
"id" varchar(100) NOT NULL,
"kind" varchar(100) NOT NULL,
"revision" int4 NOT NULL,
"value" jsonb
);
This works in PostgreSQL 12 and later with jsonpath support. If you do not have jsonpath, then please leave a comment.
with data as (
select '{
"urlName" : "testurl",
"countryside" : "",
"description" : "",
"my_items" : [
{
"id" : "AAA"
},
{
"name" : "TestRZ",
"id" : "BBB",
"description" : ""
}
],
"name" : "TheName"
}'::jsonb as stuff
)
select jsonb_set(stuff, '{my_items}',
jsonb_path_query_array(stuff->'my_items', '$ ? (#."id" <> "AAA")'))
from data;
jsonb_set
---------------------------------------------------------------------------------------------------------------------------------------------------
{"name": "TheName", "urlName": "testurl", "my_items": [{"id": "BBB", "name": "TestRZ", "description": ""}], "countryside": "", "description": ""}
(1 row)
To update the table directly, the statement would be:
update data
set value = jsonb_set(value, '{my_items}',
jsonb_path_query_array(value->'my_items',
'$ ? (#."id" <> "AAA")'));
This works for versions before PostgreSQL 12:
with data as (
select 1 as id, '{
"urlName" : "testurl",
"countryside" : "",
"description" : "",
"my_items" : [
{
"id" : "AAA"
},
{
"name" : "TestRZ",
"id" : "BBB",
"description" : ""
}
],
"name" : "TheName"
}'::jsonb as stuff
), expand as (
select d.id, d.stuff, e.item, e.rn
from data d
cross join lateral jsonb_array_elements(stuff->'my_items') with ordinality as e(item, rn)
)
select id, jsonb_set(stuff, '{my_items}', jsonb_agg(item order by rn)) as new_stuff
from expand
where item->>'id' != 'AAA'
group by id, stuff;
id | new_stuff
----+---------------------------------------------------------------------------------------------------------------------------------------------------
1 | {"name": "TheName", "urlName": "testurl", "my_items": [{"id": "BBB", "name": "TestRZ", "description": ""}], "countryside": "", "description": ""}
(1 row)
The direct update for this is a little more involved:
with expand as (
select d.id, d.value, e.item, e.rn
from data d
cross join lateral jsonb_array_elements(value->'my_items')
with ordinality as e(item, rn)
), agg as (
select id, jsonb_set(value, '{my_items}', jsonb_agg(item order by rn)) as new_value
from expand
where item->>'id' != 'AAA'
group by id, value
)
update data
set value = agg.new_value
from agg
where agg.id = data.id;

Subset a JSON Object with MySQL Query

I have a MySQL database and one of the tables is called 'my_table'. In this table, one of the columns is called 'my_json_column' and this column is stored as a JSON object in MySQL. The JSON object has about 17 key:value pairs (see below). I simply want to return a "slimmed-down" JSON Object from a MySQL query that returns 4 of the 17 fields.
I have tried many different MySQL queries, see below, but I can't seem to get a returned subset JSON Object. I am sure it is simple, but I have been unsuccessful.
Something like this:
SELECT
json_extract(my_json_column, '$.X'),
json_extract(my_json_column, '$.Y'),
json_extract(my_json_column, '$.KB'),
json_extract(my_json_column, '$.Name')
FROM my_table;
yields:
5990.510000 90313.550000 5990.510000 "Operator 1"
I want to get this result instead (a returned JSON Object) with key value pairs:
[ { X: 5990.510000, Y: 90313.550, KB: 2105, Name: "Well 1" } ]
Sample data:
{
"Comment" : "No Comment",
"Country" : "USA",
"County" : "County 1",
"Field" : "Field 1",
"GroundElevation" : "5400",
"Identifier" : "11435358700000",
"Interpreter" : "Interpreter 1",
"KB" : 2105,
"Name" : "Well 1",
"Operator" : "Operator 1",
"Owner" : "me",
"SpudDate" : "NA",
"State" : "MI",
"Status" : "ACTIVE",
"TotalDepth" : 5678,
"X" : 5990.510000,
"Y" : 90313.550
}
Thank you in advance.
Use JSON_OBJECT(), available since MySQL 5.6:
Evaluates a (possibly empty) list of key-value pairs and returns a JSON object containing those pairs
SELECT
JSON_OBJECT(
'X', json_extract(my_json_column, '$.X'),
'Y', json_extract(my_json_column, '$.Y'),
'KB', json_extract(my_json_column, '$.KB'),
'Name', json_extract(my_json_column, '$.Name')
) my_new_json
FROM my_table;
This demo on DB Fiddle with your sample data returns:
| my_new_json |
| ----------------------------------------------------------- |
| {"X": 5990.51, "Y": 90313.55, "KB": 2105, "Name": "Well 1"} |

how to get projections in mongodb with group operator

I have a table with columns Column1 & Column2 which looks like this
Colum1 Column2
A 1
A 2
A 3
B 2
B 4
B 6
If I perform following SQL in MYSQL
SELECT Column1, Column2, count(*) from Table group by Column1;
Result is
Column1 Column2 Count(*)
A 1 3
B 2 3
I want to execute similar query on MONGODB
I tried
QUERY1: db.table.aggregate({$group: {_id:"$Column1", count:{$sum:1}} })
QUERY2: db.table.aggregate({$project: {column1:1, column2:1}}, {$group: {_id:"$Column1", count:{$sum:1}} })
However the result for Query2 is same as Query1, It seems like you can not populate fields other than mentioned in $group column.
Is there a way to populate other fields in mongodb along with $group operator ?
I'm not sure I read the mysql query correctly, and I don't understand why this is particularly useful, but $first seems to accomplish the same thing.
However, as mentioned in the $first documentation, the outcome depends on the sorting so you should include a sorting criterion.
Data (column names shortened for brevity)
> db.foo.insert({"C1" : "A", "C2" : 1});
> db.foo.insert({"C1" : "A", "C2" : 2});
> db.foo.insert({"C1" : "A", "C2" : 3});
> db.foo.insert({"C1" : "B", "C2" : 2});
> db.foo.insert({"C1" : "B", "C2" : 4});
> db.foo.insert({"C1" : "B", "C2" : 6});
Aggregation Query
> db.foo.aggregate({$group: {_id:"$C1", C2: { $first: "$C2" }, count:{$sum:1}} })
Results
{
"result" : [
{
"_id" : "B",
"C2" : 2,
"count" : 3
},
{
"_id" : "A",
"C2" : 1,
"count" : 3
}
],
"ok" : 1
}