Turn Rows into Multiple elements in JSON - json

I have 1 order number which contains 4 skus, each sku is linked to 3 categories:
I need to write a SQL statement to convert this into JSON format which involves subquery and multiple elements in an array. Basically I need it to look like this:
{
"order_number": "WEB000000000",
"order_items": [
{
"sku": 111111111,
"categories": ["Checked Shirts", "Mens", "Shirts"]
},
{
"sku": 333333333,
"categories": ["Accessories & Shoes", "Mens Accessories", "Socks"]
},
{
"sku": 666666666,
"categories": ["Checked Shirts", "Mens", "Shirts"]
},
{
"sku": 999999999,
"categories": ["Nightwear", "Slippers", "Womens"]
}
]
}
Here's what I have so far but I just can't get it quite right:
DROP TABLE IF EXISTS ##Data;
CREATE TABLE ##Data
(
order_number varchar(100),
sku bigint,
categories varchar(100)
);
INSERT INTO ##Data
select 'WEB000000000', 111111111, 'Mens'
union all select 'WEB000000000', 111111111, 'Shirts'
union all select 'WEB000000000', 111111111, 'Checked Shirts'
union all select 'WEB000000000', 333333333, 'Accessories & Shoes'
union all select 'WEB000000000', 333333333, 'Mens Accessories'
union all select 'WEB000000000', 333333333, 'Socks'
union all select 'WEB000000000', 666666666, 'Mens'
union all select 'WEB000000000', 666666666, 'Shirts'
union all select 'WEB000000000', 666666666, 'Checked Shirts'
union all select 'WEB000000000', 999999999, 'Womens'
union all select 'WEB000000000', 999999999, 'Nightwear'
union all select 'WEB000000000', 999999999, 'Slippers'
SELECT * FROM ##Data;
select OUTER1.[order_number] as [order_number],
(select OSL.[order_number],
(select [sku],
(select [categories]
from ##Data skus
where order_item.[order_number] = skus.[order_number]
and order_item.[sku] = skus.[sku]
GROUP BY [categories]
FOR JSON PATH) as categories
from ##Data order_item
where order_item.[order_number] = OSL.[order_number]
GROUP BY [order_number], [sku]
FOR JSON PATH) as order_items
from ##Data OSL
where OSL.[order_number]=OUTER1.[order_number]
group by OSL.[order_number]
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER) AS JSON
from ##Data OUTER1
group by OUTER1.[order_number]
drop table ##Data

Related

Json in Postgresql

I'm learning Postgresql and Json.
I have for example database like that:
CREATE TABLE employees (
employee_id serial primary key,
department_id integer references departments(department_id),
name text,
start_date date,
fingers integer,
geom geometry(point, 4326)
);
CREATE TABLE departments (
department_id bigint primary key,
name text
);
INSERT INTO departments
(department_id, name)
VALUES
(1, 'spatial'),
(2, 'cloud');
INSERT INTO employees
(department_id, name, start_date, fingers, geom)
VALUES
(1, 'Paul', '2018/09/02', 10, 'POINT(-123.32977 48.40732)'),
(1, 'Martin', '2019/09/02', 9, 'POINT(-123.32977 48.40732)'),
(2, 'Craig', '2019/11/01', 10, 'POINT(-122.33207 47.60621)'),
(2, 'Dan', '2020/10/01', 8, 'POINT(-122.33207 47.60621)');
How could i do so i could get the data like this:
[
{
"department_name": "cloud",
"employees": [
{
"name": "Craig",
"start_date": "2019-11-01"
},
{
"name": "Dan",
"start_date": "2020-10-01"
}
]
},
{
"department_name": "spatial",
"employees": [
{
"name": "Paul",
"start_date": "2018-09-02"
},
{
"name": "Martin",
"start_date": "2019-09-02"
}
]
}
]
follow this link: https://dba.stackexchange.com/questions/69655/select-columns-inside-json-agg/200240#200240
CREATE TEMP TABLE x (
name text,
start_date date
);
WITH cte AS (
SELECT
d.name AS department_name,
json_agg((e.name, e.start_date)::x) AS employees
FROM
departments d
JOIN employees e ON d.department_id = e.department_id
GROUP BY
1
)
SELECT
json_agg((row_to_json(cte.*)))
FROM
cte;

Gouping and suming multiple columns

I have a two tables one is products that has productid, productname, customerid1 and quantity
and another customers table that has customerid2,customername and dates
what i want to do is collect all the customerid2 from customers table between two dates.
then match those ids to customerid1 in the products table with a join.
then group all the products by name sum their quantity,
then group all the customers by name for each product and sum their total quantity.
edit: I could use a subquery if necessary or seperate queries entirely. whatever works
**customers**
Column , Column, Column
customerid2:1, name:jon, date:2020
customerid2:2, name:steve, date:2020
customerid2:3, name:ted, date:2020
customerid2:4, name:ned, date:2020
**products**
Column , Column , Column , Column
productid:3 , productname:car, customerid1:1, qty,5
productid:3 , productname:car, customerid1:2, qty,5
productid:1 , productname:boat, customerid1:3, qty,1
productid:1 , productname:boat, customerid1:4, qty,2
productid:3 , productname:car, customerid1:1, qty,5
the final output should be:
car total:15
customer id:1 name:jon qty:10
customer id:2 name:steve qty:5*
boat total:3
customer id:3 name:ted qty:1
customer id:4 name:ned qty:2
my code:
$sql = SELECT customerid2, name, date, productname, SUM(qty)
FROM customers
JOIN ON customerid2 = customerid1
WHERE date BETWEEN '2019' AND '2020'
GROUP BY productid, customerid2
ORDER BY qty
Mysql can't make such an output, but on application level you can use this query, to buld what ever you need
This query:
SELECT
c.customerid2, c.name,p.productname,SUM(qty) total, p1.total_sum
FROM customer c inner JOIN products p ON c.customerid2 = p.customerid1
inner Join (SELECT productid, SUM(qty) total_sum FROM products GROUP BY productid) p1
ON p.productid = p1.productid
WHERE `date` BETWEEN '2019' AND '2020'
GROUP by c.customerid2, c.name,p.productid,p.productname
ORDER by total DESC;
To get a json object as you wanted you need this
SELECT
json_object('product', CONCAT( total_sum,' ',productname), 'customer',json_result) json_result
FROM
(SELECT
productname
,totaL_SUM
,JSON_ARRAYAGG(json_object('customerid', customerid2, 'name', name,'total', total)) json_result
FROM
(SELECT
c.customerid2, c.name,p.productname,SUM(qty) total, p1.total_sum
FROM customer c inner JOIN products p ON c.customerid2 = p.customerid1
inner Join (SELECT productid, SUM(qty) total_sum FROM products GROUP BY productid) p1
ON p.productid = p1.productid
WHERE `date` BETWEEN '2019' AND '2020'
GROUP by c.customerid2, c.name,p.productid,p.productname
ORDER by total DESC) t2
GROUP BY productname,total_sum) t3
CREATE TABLE products (
`productid` INTEGER,
`productname` VARCHAR(4),
`customerid1` INTEGER,
`qty` INTEGER
);
INSERT INTO products
(`productid`, `productname`, `customerid1`, `qty`)
VALUES
('3', 'car', '1', '5'),
('3', 'car', '2', '5'),
('1', 'boat', '3', '1'),
('1', 'boat', '4', '2'),
('3', 'car', '1', '5');
✓
✓
CREATE TABLE customer (
`customerid2` INTEGER,
`name` VARCHAR(5),
`date` INTEGER
);
INSERT INTO customer
(`customerid2`, `name`, `date`)
VALUES
('1', 'jon', '2020'),
('2', 'steve', '2020'),
('3', 'ted', '2020'),
('4', 'ned', '2020');
✓
✓
SELECT
c.customerid2, c.name,p.productname,SUM(qty) total, p1.total_sum
FROM customer c inner JOIN products p ON c.customerid2 = p.customerid1
inner Join (SELECT productid, SUM(qty) total_sum FROM products GROUP BY productid) p1
ON p.productid = p1.productid
WHERE `date` BETWEEN '2019' AND '2020'
GROUP by c.customerid2, c.name,p.productid,p.productname
ORDER by total DESC;
customerid2 | name | productname | total | total_sum
----------: | :---- | :---------- | ----: | --------:
1 | jon | car | 10 | 15
2 | steve | car | 5 | 15
4 | ned | boat | 2 | 3
3 | ted | boat | 1 | 3
SELECT json_object('product', CONCAT( total_sum,' ',productname), 'customer',
json_object('customerid', customerid2, 'name', name,'total', total)) json_result
FROM
(SELECT
c.customerid2, c.name,p.productname,SUM(qty) total, p1.total_sum
FROM customer c inner JOIN products p ON c.customerid2 = p.customerid1
inner Join (SELECT productid, SUM(qty) total_sum FROM products GROUP BY productid) p1
ON p.productid = p1.productid
WHERE `date` BETWEEN '2019' AND '2020'
GROUP by c.customerid2, c.name,p.productid,p.productname
ORDER by total DESC) t2
| json_result |
| :-------------------------------------------------------------------------------- |
| {"product": "15 car", "customer": {"name": "jon", "total": 10, "customerid": 1}} |
| {"product": "15 car", "customer": {"name": "steve", "total": 5, "customerid": 2}} |
| {"product": "3 boat", "customer": {"name": "ned", "total": 2, "customerid": 4}} |
| {"product": "3 boat", "customer": {"name": "ted", "total": 1, "customerid": 3}} |
SELECT
json_object('product', CONCAT( total_sum,' ',productname), 'customer',json_result) json_result
FROM
(SELECT
productname
,totaL_SUM
,JSON_ARRAYAGG(json_object('customerid', customerid2, 'name', name,'total', total)) json_result
FROM
(SELECT
c.customerid2, c.name,p.productname,SUM(qty) total, p1.total_sum
FROM customer c inner JOIN products p ON c.customerid2 = p.customerid1
inner Join (SELECT productid, SUM(qty) total_sum FROM products GROUP BY productid) p1
ON p.productid = p1.productid
WHERE `date` BETWEEN '2019' AND '2020'
GROUP by c.customerid2, c.name,p.productid,p.productname
ORDER by total DESC) t2
GROUP BY productname,total_sum) t3
| json_result |
| :--------------------------------------------------------------------------------------------------------------------------------- |
| {"product": "3 boat", "customer": [{"name": "ned", "total": 2, "customerid": 4}, {"name": "ted", "total": 1, "customerid": 3}]} |
| {"product": "15 car", "customer": [{"name": "jon", "total": 10, "customerid": 1}, {"name": "steve", "total": 5, "customerid": 2}]} |
db<>fiddle here

Add count to N1QL query result in Couchbase

I have a N1QL query:
SELECT p.`ID`, p.`Name` FROM `Preferences` p WHERE `type` = "myType"
The result is a list of objects[{"ID": "123", "Name": "John"}, ...]
I want to get a result JSON such as:
{
"count": 5,
"result": [{"ID": "123", "Name": "John"}, ...]
}
How could I do this using N1QL?
SELECT
COUNT(t.ID) AS count,
ARRAY_AGG(t) AS results
FROM
(
SELECT
p.`ID`, p.`Name`
FROM
`Preferences` p
WHERE `type` = "myType"
) AS t

stuck with appending name to the sub elements in json

I have 3 tables with the following schema.
a.c1 int (pk),
a.c2 varchar(50),
a.c3 varchar(50),
b.c1 int(pk),
b.c2 int(fk) -> a.c1,
b.c3 varchar(50),
b.c4 varchar(50),
c.c1 int(pk),
c.c2 int(fk) -> b.c1,
c.c3 int(fk) -> a.c1,
c.c4 varchar(50),
c.c5 varchar(50)
I'm expecting the result to be
{
"json_doc": {
"a.c1": "val",
"a.c2": "val",
"a.c3": "val",
"b": [{
"b_c1_value": {
"b.c1": "val",
"b.c2": "val",
"b.c3": "val",
"b.c4": "val",
"c": [{
"c_c1_value": {
"c.c1": "val",
"c.c2": "val",
"c.c3": "val",
"c.c4": "val",
"c.c5": "val"
}
}]
}
}]
}
}
Can someone please help me with the right sql. I'm very very new to Postgres.
I have gotten this far:
select row_to_json(t)
from (
select
*,
(
select array_to_json(array_agg(row_to_json(d)))
from (
select
*,
(
select array_to_json(array_agg(row_to_json(dc)))
from (
select *
from c
where c.c2 = b.c1
) dc
) as c
from b
where c2 = a.c1
) d
) as b
from a
WHERE a.deployid = 19
) t;
I need key names for the arrays to be populated. I'm stuck with this. Any help is deeply appreciated!

Is there a faster way to execute the following SQL request?

I have a table that contains the following columns :
id, name, domain, added, is_verified
1, "First Google", "google.com", DATE(), 1
2, "Second Google", "google.com", DATE(), 1
3, "Third Google", "google.com", DATE(), 1
4, "First disney", "disney.com", DATE(), 1
5, "Second disney", "disney.com", DATE(), 1
6, "Third disney", "disney.com", DATE(), 0
7, "First example", "example.com", DATE(), 0
8, "Second example", "example.com", DATE(), 0
And the following request :
SELECT domain FROM mytable WHERE domain NOT IN
(SELECT domain FROM mytable WHERE is_verified = 1 GROUP BY domain)
GROUP BY domain ORDER BY added DESC;
The main idea behind this request is to get all the domain that doesn't have a is_verified at true.
In the example above, this would only return "example.com" one time.
The request works well, but takes time to execute (I have thousands of entries). Is there an other way to make this request that would be faster and efficient ?
You can use the LEFT JOIN with NULL check:
SELECT T1.Domain
FROM mytable T1
LEFT JOIN mytable T2 ON T2.domain = T1.domain AND T2.is_verified = 1
WHERE T2.ID IS NULL
Sample execution with the given data:
DECLARE #TESTDOMAIN TABLE (id int, name varchar(100), domain varchar (100), added datetime, is_verified bit)
insert into #testdomain (id, name, domain, added, is_verified)
SELECT 1, 'First Google', 'google.com', GETDATE(), 1 UNION
SELECT 2, 'Second Google', 'google.com', GETDATE(), 1 UNION
SELECT 3, 'Third Google', 'google.com', GETDATE(), 1 UNION
SELECT 4, 'First disney', 'disney.com', GETDATE(), 1 UNION
SELECT 5, 'Second disney', 'disney.com', GETDATE(), 1 UNION
SELECT 6, 'Third disney', 'disney.com', GETDATE(), 0 UNION
SELECT 7, 'First example', 'example.com', GETDATE(), 0 UNION
SELECT 8, 'Second example', 'example.com', GETDATE(), 0
SELECT T1.Domain
FROM #TESTDOMAIN T1
LEFT JOIN #TESTDOMAIN T2 ON T2.domain = T1.domain AND T2.is_verified = 1
WHERE T2.ID IS NULL
SELECT domain
FROM mytable
group by domain
having max(is_verified) = 0
ORDER BY max(added) DESC
I added the order by clause. You have to decide which added record you want to take for each domain. I chose the max added value of a domain.
Why do you have to use a sub select? Wouldn't that deliver the same result?
SELECT domain
FROM mytable
GROUP BY domain
HAVING sum(is_verified)<1;