Multiple cross apply in SQL for a row with json - json

I have a row:
id, shipping_data, line_data
0, '[{"name": "Greg", "Address": "test address"}]', '[{"products": "apple", "cost": "0.50"'}'
and I want to expand the row to display all data in one row.
I tried using multiple cross applies:
SELECT id, A.*, B.*
FROM table t
CROSS APPLY OPENJSON(t.[shipping_data])
WITH (
name nvarchar(max),
Address nvarchar(max)
) A;
CROSS APPLY OPENJSON(t.[line_data])
WITH (
products nvarchar(max),
cost nvarchar(max)
) B;

Related

how to add value to json type column in sub-query

I have to combine recordObj and recTime
I tried json_insert function to add recTime property in recordObj in select statement
It is not returning any records and just giving OK message
note : I can't change table structure.
mysql sp:
CREATE DEFINER=`root`#`localhost` PROCEDURE `records_get_upcomings`(in p_parent varchar(15))
BEGIN
WITH RECURSIVE cte (p_parent) AS (
SELECT child FROM connections WHERE parent = p_parent
UNION ALL
SELECT child FROM connections JOIN cte on connections.parent = cte.p_parent
)
select recordid, `current`, group_concat(past) as past from (
select * from
(
select cur.recordObj as `current`, past.recordObj as past, cur.recordid as recordid from
(select recordid, json_insert(recordObj, '$recTime', recTime) as recordObj, rec_status from records inner join cte on records.`from` = cte.p_parent) cur
cross join
(select recordid, json_insert(recordObj, '$recTime', recTime) as recordObj, rec_status from records inner join cte on records.`from` = cte.p_parent and records.`from` = cte.p_parent) past
where past.rec_status = 1 and cur.rec_status = 0 and past.recordid = cur.recordid
) as a
union
(
select recordObj as `current`, null as past, recordid from records inner join cte on records.`from` = cte.p_parent where rec_status = 0
)
) as t group by `current`;
END
records table :
from -> varchar
recordObj -> json
recordid -> varchar
recTime -> datetime
rec_status -> tinyint
u_rec_id -> int
any help is appreciated...

Update Mysql Column of JSON array via SQL

I am storing a list of integers as JSON array inside the column called ConvertedIds inside a table SelectionLogs
The type of column is MediumText and some of the example values of the column are [290766,319075,234525,325364,3472,34241,85643,11344556,88723,656378]
I am using following sql to generate the list of IDs from the column as rows
SELECT hm.id FROM SelectionLogs hlog,
JSON_TABLE(ConvertedIds, '$[*]' columns (Id int path '$')) AS hm
And then following query to extract further informations from other tables like
SELECT hm.id,hc.firstname ,hc.lastname ,hc.email FROM SelectionLogs hlog,
JSON_TABLE(ConvertedIds, '$[*]' columns (Id int path '$')) AS hm
LEFT JOIN contacts hc ON hc.Id = hm.id
Now i have to update this column based on the presence of a given value of IDs
For example if an ID exists in this column on any rows , i have to update the array after removing the ID
For example: [1,2,3,4,5,6,7] If ID : 3 exists , remove 3 and update column as [1,2,4,5,6,7]
I can use the following query to find the records from table SelectionLogs with given id present in column ConvertedIds
SELECT DISTINCT hlog.Id FROM SelectionLogs hlog,
JSON_TABLE(ConvertedIds, '$[*]' columns (Id int path '$')) AS hm
WHERE hm.id=427529
Now i have plans to iterate through each rows from my console program written in c#
foreach row in result
List<int> columnIds = read from column ConvertedIds as list of int
Remove the given int number from List
Update column ConvertedIds for given rowId refreshed List
Can i perform the updation via SQL itself ?
DEMO fiddle with some explanations.
-- source data
CREATE TABLE t1 (id INT, val JSON)
SELECT 1 id, '[1,2,3]' val UNION SELECT 2, '[3,4,5]' UNION SELECT 3, '[5,6,7]';
CREATE TABLE t2 (id INT) SELECT 1 id UNION SELECT 4;
-- UPDATE source table
UPDATE t1
JOIN ( SELECT t1.id, JSON_ARRAYAGG(jsontable.id) val
FROM t1
CROSS JOIN JSON_TABLE(t1.val,
'$[*]' COLUMNS (id INT PATH '$')) jsontable
LEFT JOIN t2 ON t2.id = jsontable.id
WHERE t2.id IS NULL
GROUP BY t1.id ) data_for_update USING (id)
SET t1.val = data_for_update.val;

Cannot unnest json in postgres

create table json_example as
select '[{"a":1,"b":"foo"},{"a":"2","c":"bar"}]'::jsonb as value
select * from json_example
the following is working fine:
select * from json_array_elements('[{"a":1,"b":"foo"},{"a":"2","c":"bar"}]')
And i want to do the same, only difference that json is coming from a table. how to do the same using json_example table value field?
cross join json_array_elements with the table
select j.* from json_example cross join
json_array_elements(value) as j
DEMO

distinct values of different columns

I'm not sure it's possible.
I have a table with 3 columns, and I want to get different values of each one, there is an example:
A B C
--------------------
a1 b1 c1
a1 b2 c2
a1 b3 c1
The expected result is:
A B C
-----------------
a1 b1 c1
b2 c2
b3
So, it will be the union of:
SELECT DISTINCT A FROM myTable
SELECT DISTINCT B FROM myTable
SELECT DISTINCT C FROM myTable
Using UNION I get the result in one column.
Is this posible to do?
Please try the following...
SELECT COALESCE( a, '' ) AS a,
COALESCE( b, '' ) AS b,
COALESCE( c, '' ) AS c
FROM ( SELECT a,
ROW_NUMBER() OVER ( ORDER BY a ) AS recordNumber
FROM ( SELECT a
FROM myTable
GROUP BY a
) aFinder
) aNumberedFinder
FULL JOIN ( SELECT b,
ROW_NUMBER() OVER ( ORDER BY b ) AS recordNumber
FROM ( SELECT b
FROM myTable
GROUP BY b
) bFinder
) bNumberedFinder ON bNumberedFinder.recordNumber = aNumberedFinder.recordNumber
FULL JOIN ( SELECT c,
ROW_NUMBER() OVER ( ORDER BY c ) AS recordNumber
FROM ( SELECT c
FROM myTable
GROUP BY c
) cFinder
) cNumberedFinder ON cNumberedFinder.recordNumber = aNumberedFinder.recordNumber
OR cNumberedFinder.recordNumber = bNumberedFinder.recordNumber;
This statement starts with the following subquery...
SELECT a
FROM myTable
GROUP BY a
This subquery produces a list of the unique values in field a. The following subquery reproduces this list with record (aka row) numbers...
SELECT a,
ROW_NUMBER() OVER ( ORDER BY a ) AS recordNumber
FROM ( SELECT a
FROM myTable
GROUP BY a
) aFinder
Similar subqueries are used to produce numbered lists of the unique values in fields b and c.
A FULL OUTER JOIN (abbreviated here to FULL JOIN) is then performed between the lists for a and b, with their record numbers being used as the common / joining value.
Note : An INNER JOIN would only have returned as many records as there are in the shorter list of the two. A LEFT JOIN would only have been effective if the list on the left of the JOIN were of greater or longer length than the list on the right. Similar logic applies to the usage of a RIGHT JOIN. A FULL JOIN will join the two lists in the manner of a LEFT JOIN or RIGHT JOIN irrespective of which list is longer.
A FULL JOIN is then performed between the above joined dataset and the list for c where it finds a common value in either list.
The values of a, b and c are then selected from the finally joined dataset, with the COALESCE() function replacing the occurrence of any NULL values, such as those generated by the joining process, with the empty string ('')
If you have any questions or comments, then please feel free to post a Comment accordingly.
Appendix
My statement was tested against a database created using the following script...
CREATE TABLE myTable
(
a VARCHAR( 5 ),
b VARCHAR( 5 ),
c VARCHAR( 5 )
);
INSERT INTO myTable ( a,
b,
c
)
VALUES ( 'a1', 'b1', 'c1' ),
( 'a1', 'b2', 'c2' ),
( 'a1', 'b3', 'c1' );
Further Reading
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/coalesce-transact-sql (on using the COALESCE() function in Transact-SQL)
https://www.w3schools.com/sql/sql_join.asp (on the various types of horizontal JOIN - the Venn diagram is useful)
https://technet.microsoft.com/en-us/library/ms187518(v=sql.105).aspx (on using OUTER JOIN in SQL-Server)
https://learn.microsoft.com/en-us/sql/t-sql/functions/row-number-transact-sql (on using ROW_NUMBER() in Transact-SQL)

Multiple matches on same row

Say for example I have one Order coupled with multiple items.
How do I list them on the same row (for example 3 items) ?
I already tried this
SELECT order.ID, item.name , item.qty , item2.name,item2.qty,item3.name,item3.qty
FROM order
JOIN item ON order.id = item.id
JOIN item as item2 ON order.id = item2.id
JOIN item as item3 ON order.id = item3.id
But how to avoid selecting the same item multiple times ?
Thanks in advance
In TSQL you can write a query as:
DECLARE #order TABLE (id int)
INSERT INTO #order VALUES (1)
DECLARE #item TABLE (id INT,NAME VARCHAR(10),qty INT)
INSERT INTO #item VALUES (1,'A',1),(1,'B',1),(1,'C',3)
SELECT
O.id AS OrderId,
STUFF
(
(
SELECT ', Name:' + NAME + ', Qty:' + CAST (qty AS VARCHAR(10))
FROM #item I
WHERE I.Id = O.Id
ORDER BY I.Id
FOR XML PATH(''), type
).value('.', 'varchar(max)'), 1, 1, ''
) AS Models
FROM
#order O