Postgresql JSON Sql coding - json

How to write JSON SQL coding for the below json data:
{
"orderSystem":"SAP",
"orderHeader":{
"salesDoc":"0011214280",
"soldTo":"0000089890",
"createDate":"2020-01-02",
"purchNo":"2020-00-16213",
"billingStatus":"billed",
"ecomStatus":"Complete/Invoiced",
"purchDate":"2020-01-02",
"netValHd":"33416.500000000",
"taxesHd":"0.000000000",
"currency":"USD"
},
"orderItems":[
{
"docNumber":"0011214280",
"itmNumber":"000100",
"netValue":"33416.500000000",
"currency":"USD",
"shipments":[
{
"docNumber":"0011214280",
"itmNumber":"000100",
"scheduleLine":"0001",
"material":"000000000016121362"
}
]
}
],
"invoices":[
{
"billingDoc":"0048471944",
"docCategory":"M",
"currency":"USD",
"status":"CLOSED",
"invoiceUrl":"/ZSD_BILLING_API_GET_PDF"
}
]
}
Here "orderSystem":"SAP" is hard coded value. Then all "orderHeader" tags are from sales_order table. "orderItems" tags from sales_order_item table. "shipments" are from sales_order_shipment table. "invoices" are from invoice table.
sales_order table have single record for an order.
sales_order_item table may have multiple records for an order.
sales_order_shipment table may have multiple records for an order.
invoices table may have multiple records for an order.
Here joining column for all table is "salesDoc" column. How to achieve it sql json query?
Example i am giving input as salesDoc data. Then i need to pull the data in the above json format.

Here is the answer,
select row_to_json(tab)
from (
select 'SAP' sourceSystem,
(
select row_to_json(od)
from (
select sales_order_header.salesDoc,sales_order_header.soldTo,sales_order_header.createDate,sales_order_header.purchNo,sales_order_header.billingStatus,sales_order_header.ecomStatus,sales_order_header.purchDate,sales_order_header.netValHd,sales_order_header.taxesHd,sales_order_header.currency
) od
) as orderHeader,
(select array_to_json(array_agg(row_to_json(li))) from (
select sales_order_line.docNumber,sales_order_line.itmNumber,sales_order_line.netValue,sales_order_line.currency from
ecommerce.sales_order_line sales_order_line where sales_order_header.sales_ordr_no = sales_order_line.sales_ordr_no) li )as orderItems,
(select array_to_json(array_agg(row_to_json(ss))) from (
select shipment.docNumber,shipment.itmNumber,shipment.scheduleLine,shipment.material
from ecommerce.sales_order_shipment shipment where sales_order_header.sales_ordr_no = sales_order_shipment.sales_ordr_no) ss )as shipments,
(select array_to_json(array_agg(row_to_json(iv))) from (
select invoices.billingDoc,invoices.docCategory,invoices.currency ,invoices.status, invoices.invoiceUrl
from ecommerce.sales_order_invoices invoices where sales_order_header.sales_ordr_no = invoices.sales_ordr_no) iv )as invoices,
from ecommerce.sales_order_header as sales_order_header
) tab
I went through the below link and it was very useful for my case
https://hashrocket.com/blog/posts/faster-json-generation-with-postgresql

Related

sql -Extract the second key in a json string

I have some tables that contains the payment details of students. In one of the tables, a column collects data in json string.
I want to extract the value of amount from the string below. However, you would notice that key 1 has amount and key 2 has amount too.
After extracting amount, I'm obviously getting the values for the two keys, but I want to extract only the amount value in key 2
{"1":{"amount":"500","date":"2023-01-06","amount_discount":"5500","amount_fine":"0","description":"","collected_by":"Super Admin(356)","payment_mode":"Cash","received_by":"1","inv_no":1},
"2":{"amount":"49500","date":"2023-01-22","amount_discount":"0","amount_fine":"0","description":"Being payment for tuition only","collected_by":"Juliet OLAJIDE(S20170181)","payment_mode":"bank_transfer","received_by":"32","inv_no":2}}
Below is my query:
SELECT student_fees_master.*,JSON_EXTRACT(student_fees_deposite.amount_detail, '$.*.amount') AS `deposit`
FROM `student_fees_master`
INNER JOIN fee_session_groups on fee_session_groups.id = student_fees_master.fee_session_group_id
INNER JOIN fee_groups_feetype on fee_groups_feetype.fee_session_group_id = fee_session_groups.id
INNER JOIN fee_groups on fee_groups.id=fee_groups_feetype.fee_groups_id
INNER JOIN feetype on feetype.id=fee_groups_feetype.feetype_id
LEFT JOIN student_fees_deposite on
student_fees_deposite.student_fees_master_id=student_fees_master.id
and student_fees_deposite.fee_groups_feetype_id=fee_groups_feetype.id
WHERE fee_groups_feetype.feetype_id=1
This is what I'm getting:
["500", "49500"]
But I want this:
["49500"]
How do I go about this?
You can do it as follows :
with cte as (
select '{"1":{"amount":"500","date":"2023-01-06","amount_discount":"5500","amount_fine":"0","description":"","collected_by":"Super Admin(356)","payment_mode":"Cash","received_by":"1","inv_no":1},
"2":{"amount":"49500","date":"2023-01-22","amount_discount":"0","amount_fine":"0","description":"Being payment for tuition only","collected_by":"Juliet OLAJIDE(S20170181)","payment_mode":"bank_transfer","received_by":"32","inv_no":2}}' as deposit
)
select JSON_EXTRACT(deposit->"$.*", "$[1].amount") AS `deposit`
from cte;
Demo here
A simple solution might be like this:
ORDER BY deposit DESC LIMIT 1

Left outer Join in Cube JS

I have a requirement to join two tables in cube js. First table has list of customers. Second table has list orders with customer ids with purchase date. I have to display the total orders placed by the customer with date filter. If the there is an order available in the second table I am able to get the customer row with the order count. If the date range is changed and if no orders available it should show zero against customer, instead no row is returned.
Any work around or help on this is much appreciated.
you could specify the left outer join in the SQL property of the cube:
cube(`Users`, {
sql: `SELECT * from orders LEFT OUTER JOIN customers,
})
In your dimensions specify a new dimension that takes 1 if order id is not null and takes 0 else, as follows:
hasOrder: {
type: `number`,
case: {
when: [
{ sql: `${CUBE}.order_id is null`, label: { sql: Number("0") } },
{ sql: `${CUBE}.order_id is not null`, label: { sql: Number("1") } }
],
}
},
then define a measure that sums the number of Orders, it should return O for customers with no orders:
measures: {
ordersCompletedCount: {
type: `sum`,
sql: `${CUBE.hasOrder}`
},
},

Access 2016. Expression

I have a table t01PriceList with fields including. "Date","LatestPrice01","StockNumber01".
Another table t01StockItem with fields including "LatestPrice02", "StockNumber02".
I want an expression in t01StockItem that returns the amount from "LatestPrice01" at the latest date. There are multiple records in t01Pricelist against the same StockItem.
I tried Dlookup("LatestPrice01","t01PriceList",Dmax(Date))
Thank you.
Create a query to retrieve the latest prices:
Select
StockNumber01, LatestPrice01
From
t01PriceList As A,
(Select StockNumber01, Max([Date]) As LatestDate
From t01PriceList
Group By StockNumber01) As T
Where
A.StockNumber01 = T.StockNumber01 And
A.Date = T.LatestDate
Then join this with t01StockItem on the StockNumber.

Get Last Column in Each Different Customer ID

I have a table with Invoice Date and Customer ID (among other data, of course). I'm looking to display the longest invoice date in the future in the table for each customer.
I am currently using this MySQL in the WHERE:
WHERE o70vm_invoices_invoices.invoice_date = (SELECT MAX(o70vm_invoices_invoices.invoice_date) FROM o70vm_invoices_invoices)";
This code currently displays the oldest date in the column for just one customer.
I'm including my entire MySQL query below, please keep in mind that I'm having to pull from various tables to display the data I need.
$query = "SELECT
o70vm_invoices_contacts.name AS 'Parent_Name',
o70vm_invoices_contacts.id AS 'Parent_ID',
o70vm_invoices_contacts.company AS 'Children',
o70vm_invoices_contacts.active AS 'Active',
o70vm_invoices_invoices.id AS 'Invoice_ID',
o70vm_invoices_invoices.user_id AS 'Parent_ID_on_Invoice',
o70vm_invoices_invoices.invoice_num AS 'Invoice_Num',
o70vm_invoices_invoices.invoice_date AS 'Invoice_Date',
o70vm_invoices_invoices.invoice_duedate AS 'Invoice_Date_Due',
o70vm_invoices_payments.invoice_id,
o70vm_invoices_payments.id,
o70vm_invoices_payments.payment_amount AS 'Payment_Amount',
o70vm_invoices_payments.payment_datetime AS 'Payment_Date',
o70vm_invoices_payments.payment_duedate,
o70vm_invoices_payments.payment_status AS 'Payment_Status',
o70vm_invoices_payments.payment_description AS 'Payment_Descript',
o70vm_invoices_payments.payment_type AS 'Payment_Type'
FROM o70vm_invoices_invoices, o70vm_invoices_contacts, o70vm_invoices_payments
WHERE
o70vm_invoices_contacts.id = o70vm_invoices_invoices.user_id
AND
o70vm_invoices_payments.invoice_id = o70vm_invoices_invoices.id
AND
o70vm_invoices_invoices.invoice_date < '2099-01-01'
AND
o70vm_invoices_contacts.active = 1
AND o70vm_invoices_invoices.invoice_date = (SELECT MAX(o70vm_invoices_invoices.invoice_date) FROM o70vm_invoices_invoices)";
If I use a GROUP BY:
GROUP BY o70vm_invoices_contacts.id
I can pull each customer to display but it does not display the last future invoice in the table.
Based on Stefan's comments below, here is my revised subquery:
$query = "SELECT *
FROM ( SELECT
o70vm_invoices_contacts.name AS 'Parent_Name',
o70vm_invoices_contacts.id AS 'Parent_ID',
o70vm_invoices_contacts.company AS 'Children',
o70vm_invoices_contacts.active AS 'Active',
o70vm_invoices_invoices.id AS 'Invoice_ID2',
o70vm_invoices_invoices.user_id AS 'Parent_ID_on_Invoice',
o70vm_invoices_invoices.invoice_num AS 'Invoice_Num',
o70vm_invoices_invoices.invoice_date AS 'Invoice_Date',
o70vm_invoices_invoices.invoice_duedate AS 'Invoice_Date_Due',
o70vm_invoices_payments.invoice_id,
o70vm_invoices_payments.id,
o70vm_invoices_payments.payment_amount AS 'Payment_Amount',
o70vm_invoices_payments.payment_datetime AS 'Payment_Date',
o70vm_invoices_payments.payment_duedate,
o70vm_invoices_payments.payment_status AS 'Payment_Status',
o70vm_invoices_payments.payment_description AS 'Payment_Descript',
o70vm_invoices_payments.payment_type AS 'Payment_Type'
FROM o70vm_invoices_invoices, o70vm_invoices_contacts, o70vm_invoices_payments
WHERE
o70vm_invoices_contacts.id = o70vm_invoices_invoices.user_id
AND
o70vm_invoices_payments.invoice_id = o70vm_invoices_invoices.id
AND
o70vm_invoices_invoices.invoice_date < '2099-01-01'
AND
o70vm_invoices_contacts.active = 1
ORDER BY o70vm_invoices_invoices.invoice_date DESC
) AS tmp
GROUP BY tmp.id";
This query lists the first invoice date and not the last invoice date. If I change the order to ASC, it just sorts the results of the first invoice date.
Any help, much appreciated.
Best way might be to make use of a sub query:
SELECT *
FROM (
SELECT *
FROM o70vm_invoices_invoices
ORDER BY invoice_date DESC
) AS tmp
GROUP BY tmp.id
I'm sure there is a better way to do this; however, this works.
I just added MAX inside my query as such:
max(o70vm_invoices_invoices.invoice_date) AS 'Invoice_Date',
and this lists the furthest date for each customer.

Converting a SQL query with group by into LINQ query

I'm stuggling to replicate a SQL query into LINQ.
Can any one help?
SQL:
SELECT tblInvoice.lngID AS InvoiceID,
tblInvoice.dtTimeStamp AS InvoiceDate,
tblInvoice.strReference,
tblInvoice.fltTotalValue,
max(Project.ProjectID) AS ProjectID,
max(Project.ProjectName) AS ProjectName,
max(Project.Location) AS ProjectLocation
FROM tblInvoice INNER JOIN
tblInvoiceLine ON tblInvoice.lngID = tblInvoiceLine.lngInvoiceID
WHERE (tblInvoice.intStatus != 0)
AND (tblInvoice.lngPersonID = #PersonID)
GROUP BY tblInvoice.lngID, tblInvoice.dtTimeStamp, strReference, fltTotalValue
ORDER BY tblInvoice.lngID DESC
LINQ so far:
var invoices = from inv in db.TblInvoices
join invLine in db.TblInvoiceLines on inv.LngID equals invLine.LngInvoiceID
where inv.IntStatus != 0
where inv.LngPersonID == personID
group inv by new {inv.LngID,inv.DtTimeStamp,inv.StrReference,inv.FltTotalValue} into newInv
Part of the problem is that I want to do a
select new Invoice(){
}
and build up my custom Invoice object but, I cant see any of the properties in newInv.
Can any one advise?
I don't have time for a full answer now, but:
To get at properties of the key, use newInv.Key.StrReference etc
To get at aggregates (e.g. max values) use newInv.Max(x => x.ProjectId) etc
Hopefully that'll be enough to get you going. Basically, newInv will be a group of entries, with an associated key (which is what you grouped by).