How to query Oracle grouping? - sql

I have such a problem and I don't know how to solve it, can you help me? t
The query returns a result that is shown on the photo and I want to get it to be shown in one line instead of many based on type of age.
https://imgur.com/a/OA6CBpa
with x as (
select ai.invoice_id, ai.invoice_num, ai.invoice_amount, ai.amount_paid,
trial.entity_id, trial.acctd_amount, trial.entered_amount, trial.gl_date,
aps.amount_remaining, aps.gross_amount, aps.due_date, aps.payment_status_flag,
trial.gl_date - aps.due_date dni_opoznienia
from ap_invoices_all ai,
xla.xla_transaction_entities xte,
(
select nvl (tr.applied_to_entity_id, tr.source_entity_id) entity_id,
tr.source_application_id application_id,
sum (nvl (tr.acctd_unrounded_cr, 0)) - sum (nvl (tr.acctd_unrounded_dr, 0)) acctd_amount,
sum (nvl (tr.entered_unrounded_cr, 0)) - sum (nvl (tr.entered_unrounded_dr, 0)) entered_amount,
max(tr.gl_date) gl_date
from xla.xla_trial_balances tr
where 1=1
and tr.definition_code = 'AP_200_1001'
and tr.source_application_id = 200
and tr.gl_date <= fnd_date.canonical_to_date('2019-12-13') -- Data KG
group by nvl (tr.applied_to_entity_id, tr.source_entity_id),
tr.source_application_id
) trial,
ap_payment_schedules_all aps
where 1=1
and ai.invoice_id = 3568325
and nvl(xte.source_id_int_1, -99) = ai.invoice_id
and xte.ledger_id = 1001
and xte.entity_code = 'AP_INVOICES'
and xte.entity_id = trial.entity_id
and xte.application_id = trial.application_id
and ai.invoice_id = aps.invoice_id
)
select x.invoice_id, x.invoice_num, x.entity_id, x.acctd_amount, x.gl_date,
x.amount_remaining, x.gross_amount, x.due_date, x.payment_status_flag,
x.dni_opoznienia, aapl.days_start, aapl.days_to,
case
when x.dni_opoznienia between aapl.days_start and aapl.days_to then x.acctd_amount
else 0
end przedzial
from x,
ap_aging_periods aap,
ap_aging_period_lines aapl
where 1=1
and aap.period_name = 'TEST 5 okresow'
and aap.aging_period_id = aapl.aging_period_id

Based on your comment I guess you need the below
select * from (select x.invoice_id, x.invoice_num, x.entity_id, x.acctd_amount, x.gl_date,
x.amount_remaining, x.gross_amount, x.due_date, x.payment_status_flag,
x.dni_opoznienia, aapl.days_start, aapl.days_to,
case
when x.dni_opoznienia between aapl.days_start and aapl.days_to then x.acctd_amount
else 0
end przedzial
from x,
ap_aging_periods aap,
ap_aging_period_lines aapl
where 1=1
and aap.period_name = 'TEST 5 okresow'
and aap.aging_period_id = aapl.aging_period_id)
where przedzial > 0;

Related

Why is "[COUNT (*): 0]" returned instead of just "0" when executing sql query in groovy?

Why is "[COUNT (*): 0]" returned instead of just "0" when executing sql query in groovy? What can I do to return only a number?
def res = sql.firstRow("""SELECT count(*) FROM bd.pas WHERE INN = ?
AND SYSDATE >= RECDATEBEGIN AND SYSDATE < RECDATEEND AND NVL(DLL, 0) = 0
""",['test'])
println(res)
Use an alias in your query:
def res = sql.firstRow("""SELECT count(*) as num FROM bd.pas WHERE INN = ?
AND SYSDATE >= RECDATEBEGIN AND SYSDATE < RECDATEEND AND NVL(DLL, 0) = 0
""",['test'])
and then read the specific field:
println(res.num)
The firstRow() returns a GroovyRowResult which is essentially a Map.
That's why you get [COUNT (*): 0].
To get a number only out of it you can do:
def res = sql.firstRow("""SELECT count(*) FROM bd.pas ...""",['test']).values().first()

Informix divide by zero error

I have a query which is erroring out with a divide by zero error. I have isolated the part of the query which errors and tried to fix it using an NVL but it's just not going well, can someone spot my error?
select warehouse.ware_code,
warehouse.desc_text,
maingrp.maingrp_code,
maingrp.desc_text,
prodgrp.prodgrp_code,
prodgrp.desc_text,
left(product.part_code,7) Parent_Product_code,
product.part_code,
product.desc_text,
sum(salesstat.order_qty - salesstat.return_qty) Total_Sales,
sum((salesstat.order_qty - salesstat.return_qty) / 6) Average_Weekly_Sales,
sum(((salesstat.order_qty - salesstat.return_qty) / 6) * 4) Average_Monthly_Sales,
'??' Note,
sum(prodstatus.onhand_qty) Stock_On_Hand,
sum(orderstat.order_qty - orderstat.cancel_qty) Outstanding_orders,
sum(prodstatus.onhand_qty - (orderstat.order_qty - orderstat.cancel_qty)) Stock_Available,
--CASE
--WHEN nvl(sum(salesstat.order_qty - salesstat.return_qty),0) = 0
-- THEN 999
--ELSE sum(prodstatus.onhand_qty / ((salesstat.order_qty - salesstat.return_qty) / 6))
--END as Weeks_Stock_Remaining,
'??' Stock_ordered,
'??' Production_date
from
warehouse,
warereptdetl,
maingrp,
prodgrp,
product,
prodstatus,
salesstat,
orderstat,
Statint
where warehouse.cmpy_code = maingrp.cmpy_code
and warehouse.cmpy_code = warereptdetl.cmpy_code
and warehouse.cmpy_code = prodgrp.cmpy_code
and warehouse.cmpy_code = product.cmpy_code
and warehouse.cmpy_code = salesstat.cmpy_code
and warehouse.cmpy_code = prodstatus.cmpy_code
and warehouse.cmpy_code = orderstat.cmpy_code
and warehouse.cmpy_code = statint.cmpy_code
and product.ware_code = prodstatus.ware_code
and product.ware_code = warehouse.ware_code
and product.ware_code = salesstat.ware_code
and product.ware_code = orderstat.ware_code
and product.ware_code = warereptdetl.ware_code
and product.part_code = salesstat.part_code
and product.part_code = orderstat.part_code
and product.part_code = prodstatus.part_code
and product.prodgrp_code = salesstat.prodgrp_code
and product.prodgrp_code = orderstat.prodgrp_code
and product.prodgrp_code = prodgrp.prodgrp_code
and product.maingrp_code = salesstat.maingrp_code
and product.maingrp_code = orderstat.maingrp_code
and product.maingrp_code = maingrp.maingrp_code
and salesstat.year_num = statint.year_num
and salesstat.int_num = statint.int_num
and salesstat.stat_type_code = statint.type_code
and orderstat.year_num = statint.year_num
and orderstat.int_num = statint.int_num
and orderstat.stat_type_code = statint.type_code
and warehouse.cmpy_code = 'AB'
and warereptdetl.warereptgrp_code = 'NSW'
and product.ware_code = 'HP1'
and product.status_ind <> 3
and left(product.part_code,2) = '21'
and statint.year_num = 2016
and statint.int_num between 29 AND 34
--and statint.int_num = 29
and statint.type_code = 'WLY'
Group by 1,2,3,4,5,6,7,8,9
The commented out part is where I have tried to put in a fix, if I comment it out the query runs fine (albeit a bit slow).
The second part of the question is something that you may not be able to answer without having access to my database but if I run the query for 1, 2 or even 3 weeks (statint.int_num) the query comes back in under 1 minute. as soon as I push it out to 6 weeks (which is what I need) the query takes just over 40 minutes to return the results.
I can't see anywhere in the query where I have created a cartesian but I have stared at it for so long I may be missing it.
In your case statement:
sum(salesstat.order_qty - salesstat.return_qty)
may be non zero, but the individual
salesstat.order_qty - salesstat.return_qty
which is what you're dividing by, may contain zeroes.
EDIT
To clarify,
sum(prodstatus.onhand_qty / ((salesstat.order_qty - salesstat.return_qty) / 6))
may have zeroes in the denomiator because it is a sum of several fractions. Just because all of the denominators sum up to a non-zero number doesn't mean that all the denominators are non-zero.

Oracle query works in Toad Developer but not in .net application

This query works in Toad developer but not(wont return results) in an .net application in visual studio. Any clues why?
The query work if I omit the line -- having sum(total_cust_cnt) >= NVL (:customers_out, 100)
select d.region_nbr, pi.city, d.case_id, c.cause_desc cause, sum(total_cust_cnt) customers, d.total_duration_minutes
from t_om_cause_of_trouble c,
t_om_archive_hist_device d,
t_om_archive_hist_loc l,
t_om_pod_info pi
where c.cause = d.cause_of_trouble
and pi.city is not null
and pi.total_cust_cnt > 0
and pi.company = l.company
and pi.distribution_location = l.distribution_location_nbr
and l.company = d.company
and l.region_nbr = d.region_nbr
and l.outage_system = d.outage_system
and l.case_id = d.case_id
and d.first_call_date_time >= :start_date
and d.first_call_date_time <= :end_date
and d.service_request_type = 'LGTS'
and d.cause_of_trouble not in
(select distinct cs.cause from t_om_cause_by_summary cs, t_om_cause_of_trouble c
where summary_cause = 'ERROR' and cs.cause = c.cause)
and d.device_type <> 'ERR'
and d.total_duration_minutes >= 60 * NVL(:hours_out,4)
and d.total_duration_minutes > 5
and d.total_customers_affected >= NVL (:customers_out, 100)
and to_char(d.region_nbr) like :region_nbr
group by d.region_nbr, pi.city, d.case_id, c.cause_desc, d.total_duration_minutes
/* having sum(total_cust_cnt) >= NVL (:customers_out, 100) */
order by d.region_nbr, pi.city, d.case_id
)
group by region_nbr, city, cause
order by region_nbr, city, cause
) stats
where r.region = stats.region_nbr
)

Full outer join very slow

I have two tables. One is todays prices and one is yesterdays prices. There is a job which updates each table over night. Yesterdays prices is a copy of todays before it gets updated.
I am trying to create a table which shows the differences between the tables.
To do this I am using a full outer join. I am filtering down my criteria to make it faster as both tables are over 48 million rows.
My current code is like this.
WITH differ AS
(
SELECT
tAP.CustomerID, tAP.ProductID, yAP.CustomerID AS 'Yest_CustomerID', yAP.ProductID AS 'Yest_ProductID',
tAP.PDG, tAP.DiscPct1, tAP.DiscPct2,
yAP.DiscPct1 AS 'Yest_DiscPct1',
yAP.DiscPct2 AS 'Yest_DiscPct2',
CONVERT(DECIMAL(18,2),tAP.DiscPct1 - yAP.DiscPct1) AS 'DiscPct1_Difference',
CONVERT(DECIMAL(18,2),tAP.DiscPct2 - yAP.DiscPct2) AS 'DiscPct2_Difference',
tAP.internalSPANumber, yAP.internalSPANumber AS 'Yest_InternalSPANumber', tAP.SPAUniqueReference,
tAP.Project,
tAP.ExpiryDate,tAP.Subaddress, tAP.PriceType, yAP.PriceType AS 'Yest_PriceType', tAP.ListPrice,
tAP.NettPrice, yAP.NettPrice AS 'Yest_NettPrice',
CONVERT(DECIMAL(18,2),tAP.NettPrice- yAP.NettPrice) AS 'NettPrice_Difference'
FROM tbl_Prices tAP FULL OUTER JOIN tbl_Prices_Yesterday yAP ON tAP.CustomerId = yAP.CustomerID AND tAP.ProductID = yAP.ProductID
AND tAP.PDG = yAP.PDG AND tAP.Project = yAP.Project AND tAP.PriceType = yAP.PriceType
WHERE (((tAP.DiscPct1 <> yAP.DiscPct1)
OR (tAP.DiscPct2 <> yAP.DiscPct2)
OR (yAP.CustomerID IS NULL)
OR (tAP.CustomerID IS NULL)
OR (tAP.NettPrice <> yAP.NettPrice)
OR (tAP.InternalSPANumber <> yAP.InternalSPANumber))
AND
(
tAP.ProductID = '10238610' OR tAP.ProductID = '10238620'
OR tAP.ProductID = '10238621' OR tAP.ProductID = '10238687'
OR tAP.ProductID = '10238688' OR yAP.ProductID = '10238610'
OR yAP.ProductID = '10238620' OR yAP.ProductID = '10238621'
OR yAP.ProductID = '10238687' OR yAP.ProductID = '10238688')
)
)
SELECT * INTO tbl_Difference FROM differ
Anyway to make this faster?
Can you filter the 2 large tables before you try to join them using AND filter in your where?
WITH tAPcte AS
(
SELECT * -- fields you need
FROM tbl_Prices
WHERE ProductID IN ('10238610',
'10238620',
'10238621',
'10238687',
'10238688')
),
yAPcte AS
(
SELECT * -- fields you need
FROM tbl_Prices_Yesterday
WHERE ProductID IN ('10238610',
'10238620',
'10238621',
'10238687',
'10238688')
)
differ AS
(
SELECT
tAP.CustomerID, tAP.ProductID, yAP.CustomerID AS 'Yest_CustomerID', yAP.ProductID AS 'Yest_ProductID',
tAP.PDG, tAP.DiscPct1, tAP.DiscPct2,
yAP.DiscPct1 AS 'Yest_DiscPct1',
yAP.DiscPct2 AS 'Yest_DiscPct2',
CONVERT(DECIMAL(18,2),tAP.DiscPct1 - yAP.DiscPct1) AS 'DiscPct1_Difference',
CONVERT(DECIMAL(18,2),tAP.DiscPct2 - yAP.DiscPct2) AS 'DiscPct2_Difference',
tAP.internalSPANumber, yAP.internalSPANumber AS 'Yest_InternalSPANumber', tAP.SPAUniqueReference,
tAP.Project,
tAP.ExpiryDate,tAP.Subaddress, tAP.PriceType, yAP.PriceType AS 'Yest_PriceType', tAP.ListPrice,
tAP.NettPrice, yAP.NettPrice AS 'Yest_NettPrice',
CONVERT(DECIMAL(18,2),tAP.NettPrice- yAP.NettPrice) AS 'NettPrice_Difference'
FROM tAPcte tAP FULL OUTER JOIN yAPcte yAP ON tAP.CustomerId = yAP.CustomerID AND tAP.ProductID = yAP.ProductID
AND tAP.PDG = yAP.PDG AND tAP.Project = yAP.Project AND tAP.PriceType = yAP.PriceType
WHERE (((tAP.DiscPct1 <> yAP.DiscPct1)
OR (tAP.DiscPct2 <> yAP.DiscPct2)
OR (yAP.CustomerID IS NULL)
OR (tAP.CustomerID IS NULL)
OR (tAP.NettPrice <> yAP.NettPrice)
OR (tAP.InternalSPANumber <> yAP.InternalSPANumber))
)
SELECT * INTO tbl_Difference FROM differ

Progress DB, need to merge two queries

I have 2 progress database queries and I'm trying to merge them into one statement, but I am getting errors. Each of these queries simply returns a number and I would like to sum those 2 numbers together. Either that or make another query from scratch. They both take in a set of value codes for "DM1" and they both accept 1 "product".
Query 1
SELECT SUM(opn3.samt)
FROM PUB.ord ord3, PUB.opn opn3
WHERE
ord3.subsnum = opn3.subsnum
AND ord3.onum = opn3.onum
AND ord3.DM1 != ''
AND ord3.DM1 IN('XCWAJC25','WCWAMO73')
AND ord3.prdcde = 'CSC'
AND ord3.stat != 16
AND opn3.samt >= 0
GROUP BY ord3.DM1, ord3.prdcde
Query 2
SELECT SUM((-1 * opn2.samt) + ord2.samt)
FROM PUB.ord ord2, PUB.opn opn2
WHERE
ord2.subsnum = opn2.subsnum
AND ord2.onum = opn2.onum
AND ord2.DM1 != ''
AND ord2.DM1 IN('XCWAJC25','WCWAMO73')
AND ord2.prdcde = 'CSC'
AND ord2.stat = 16
AND opn2.samt < 0
GROUP BY ord2.DM1, ord2.prdcde
Merge attempt so far...
SELECT SUM(opn3.samt + (SELECT SUM((-1 * opn2.samt) + ord2.samt)
FROM PUB.ord ord2, PUB.opn opn2
WHERE
ord2.subsnum = opn2.subsnum
AND ord2.onum = opn2.onum
AND ord2.DM1 != ''
AND ord2.DM1 = ord3.DM1
AND ord2.prdcde = ord3.prdcde
AND ord2.stat = 16
AND opn2.samt < 0
GROUP BY ord2.DM1, ord2.prdcde
)) as foo
FROM PUB.ord ord3, PUB.opn opn3
WHERE
ord3.subsnum = opn3.subsnum
AND ord3.onum = opn3.onum
AND ord3.DM1 != ''
AND ord3.DM1 IN('XCWAJC25','WCWAMO73')
AND ord3.prdcde = 'CSC'
AND ord3.stat != 16
AND opn3.samt >= 0
GROUP BY ord3.DM1, ord3.prdcde
Thanks
I think this will work, although it would be nice to have sample data to verify:
SELECT COALESCE(SUM(a.samt), 0) - COALESCE(SUM(b.samt), 0)
+ COALESCE(SUM(CASE WHEN ord.stat = 16
AND b.samt < 0
THEN ord.samt END), 0)
FROM PUB.ord ord
LEFT JOIN PUB.opn a
ON a.subsnum = ord.subsnum
AND a.onum = ord.onum
AND a.samt >= 0
AND ord.stat != 16
LEFT JOIN PUB.opn b
ON b.subsnum = ord.subsnum
AND b.onum = ord.onum
AND b.samt < 0
AND ord.stat = 16
WHERE ord.DM1 IN('XCWAJC25', 'WCWAMO73')
AND ord.prdcde = 'CSC'
GROUP BY ord.DM1
Notes on query/stuff:
Always explicitly qualify joins, don't use the comma-separated FROM clause
I don't think you needed ord.DM1 != '', given that values have to be in a specific set
Putting a clause into a LEFT JOIN condition instead of the WHERE clause has a slightly different effect; it adds the condition to the join, instead of the filtering. This means that rows can be excluded based on something in the left table, regardless of whether you need the actual row (this is why ord.stat ended up in the LEFT JOINs). INNER JOINs would technically behave the same way, but it isn't usually noticeable because causing the right table to be excluded also excludes the left table.
I think this should do the trick, given the the individual queries work as intended:
SELECT sum1.tot + sum2.tot
FROM
(SELECT SUM(opn3.samt) as tot
FROM PUB.ord ord3, PUB.opn opn3
WHERE
ord3.subsnum = opn3.subsnum
AND ord3.onum = opn3.onum
AND ord3.DM1 != ''
AND ord3.DM1 IN('XCWAJC25','WCWAMO73')
AND ord3.prdcde = 'CSC'
AND ord3.stat != 16
AND opn3.samt >= 0
GROUP BY ord3.DM1, ord3.prdcde) sum1,
(SELECT SUM((-1 * opn2.samt) + ord2.samt) as tot
FROM PUB.ord ord2, PUB.opn opn2
WHERE
ord2.subsnum = opn2.subsnum
AND ord2.onum = opn2.onum
AND ord2.DM1 != ''
AND ord2.DM1 IN('XCWAJC25','WCWAMO73')
AND ord2.prdcde = 'CSC'
AND ord2.stat = 16
AND opn2.samt < 0
GROUP BY ord2.DM1, ord2.prdcde) sum2