We gebruiken het onderstaande SQL-statement om voor verkoopanalyses de historische verkoopprijzen en te relateren inkoopprijzen te bepalen. Het was nodig om Exact anders te gebruiken qua in- en verkoopproces. Vanwege samengestelde artikelen en geografische gespreide inkoop wordt de meest recent gebruikte inkoopprijs of meest nabije inkoopprijs in de toekomst teruggezocht voor een artikel.
Langzame bepaling week laatste inkoop
Specifiek de onderstaande query is erg traag geworden bij de overgang van 20.2.129 naar 20.2.141. Per artikel geeft die aan in welke week het artikel de laatste keer gekocht is geweest.
Hoe kan dit qua prestaties weer versneld worden?
De query geeft normaliter een miljoen rijen terug in 30 seconden, maar nu duurt het langer dan een half uur (daarna afgebroken).
--
-- Opzoektabel per week wanneer de laatste keer een artikel is ingekocht.
--
create or replace table plw@inmemorystorage
as
select clr.day_date
, plw.itemcode
, min(plw.por_week)
plw_por_week_min
, max(plw.sun_in_week_date)
plw_sun_in_week_date_min
from CALENDAR@DataDictionary clr
join pleweek@inmemorystorage plw
on plw.sun_in_week_date <= clr.day_date
--
-- Optimalisatie: kijk alleen vanaf de eerste besteldatum.
--
where clr.day_date >= ( select min(orderdate) from purchaselines@inmemorystorage )
and clr.day_in_week = 1
--
-- Optimalisatie: kijkt niet in de toekomst.
--
and clr.day_date <= add_months(trunc(sysdate), 1)
group
by clr.day_date
, plw.itemcode
SQL Verkoopanalyses
create or replace table stg@inmemorystorage
as
select to_date($X{startdate}) startdate
;
create or replace table sim@inmemorystorage
as
select /*+ http_disk_cache(true, true, interval '1 week') */
sim.division
, sim.item
, sim.itemcode
, sim.SupplierCode
, sim.SupplierDescription
from supplieritems sim
where sim.MainSupplier = true
;
create or replace table itm@inmemorystorage
as
select itm.*
, igp.code itemgroupcode
from itemsincremental itm
join itemgroups igp
on igp.id = itm.itemgroup
;
create or replace table tle@inmemorystorage
as
select to_char(tle.date, 'YYYYIW')
tle_week
label 'Week'
, to_char(tle.date, 'YYYYMM')
tle_maand
label 'Maand'
, -tle.amountdc
amountdc
label 'Gefactureerde Omzet'
, itm.itemgroupcode
, tle.*
from transactionlinesincremental tle
join itm@inmemorystorage itm
on itm.id = tle.item
where tle.date >= (select /*+ low_cost */ startdate from stg@inmemorystorage)
and tle.journalcode = '70'
and tle.glaccount in (select /*+ low_cost */ id from glaccountsincremental where code like '8%')
and tle.linenumber not in (0, 9998, 9999)
order
by tle.division
, tle.date
, tle.invoicenumber
, tle.linenumber
;
create or replace table sor@inmemorystorage
as
select to_char(sor.orderdate, 'YYYYIW')
sor_week
label 'Week'
, to_char(sor.orderdate, 'YYYYMM')
sor_maand
label 'Maand'
, sor.* prefix with 'sor_'
, act.* prefix with 'act_'
from SalesOrderLinesIncremental sor
join AccountsIncremental act
on act.id = sor.OrderedBy
where sor.orderdate >= (select /*+ low_cost */ startdate from stg@inmemorystorage)
and sor.linenumber = 0
;
--
-- Historische inkoopprijzen per artikel.
--
create or replace table purchaselines@inmemorystorage
as
select por.orderdate
, por.orderdate - to_number(to_char(por.orderdate, 'D'))
sun_in_week_date
, to_char(por.orderdate, 'YYYYIW')
por_week
label 'Week'
, to_char(por.orderdate, 'YYYYMM')
por_maand
label 'Maand'
, ple.itemcode
, ple.netprice
, ple.quantity
, por.ordernumber
from exactonlinerest..PurchaseOrders por
join exactonlinerest..PurchaseOrderLines ple
on ple.PurchaseOrderID = por.PurchaseOrderID
;
--
-- Maximum prijzen in een week waarin er inkopen geweest zijn
-- voor een artikel.
--
create or replace table pleweek@inmemorystorage
as
select itemcode
, por_week
, sun_in_week_date
, avg(quantity * netprice) netpricewavg
, avg(netprice) netpriceavg
, max(netprice) netpricemax
, min(netprice) netpricemin
, count(*) cnt
from purchaselines@inmemorystorage
group
by itemcode
, por_week
, sun_in_week_date
;
--
-- Opzoektabel per week wanneer de laatste keer een artikel is ingekocht.
--
create or replace table plw@inmemorystorage
as
select clr.day_date
, plw.itemcode
, min(plw.por_week)
plw_por_week_min
, max(plw.sun_in_week_date)
plw_sun_in_week_date_min
from CALENDAR@DataDictionary clr
join pleweek@inmemorystorage plw
on plw.sun_in_week_date <= clr.day_date
--
-- Optimalisatie: kijk alleen vanaf de eerste besteldatum.
--
where clr.day_date >= ( select /*+ low_cost */ min(orderdate) from purchaselines@inmemorystorage )
and clr.day_in_week = 1
--
-- Optimalisatie: kijkt niet in de toekomst.
--
and clr.day_date <= add_months(trunc(sysdate), 1)
group
by clr.day_date
, plw.itemcode
;
--
-- Bepaal per artikel wat de laatste bekende prijs is
-- per week. Als er meerdere prijzen zijn, dan wordt de hoogste
-- inkoopprijs genomen.
--
create or replace table approx_prices@inmemorystorage
as
select plw0.day_date
, plw0.itemcode
, plw0.plw_sun_in_week_date_min
, case
--
-- Weighted average price since VZKI contained all kinds of
-- shipping products.
--
when plw0.itemcode = 'iets'
then 29 /* plw1.netpricewavg */
else plw1.netpricemax
end
netpriceweek
from plw@inmemorystorage plw0
join pleweek@inmemorystorage plw1
on plw1.sun_in_week_date = plw0.plw_sun_in_week_date_min
and plw1.itemcode = plw0.itemcode
;
create or replace table sle@inmemorystorage
as
select sor.*
, sle.* prefix with 'sle_'
, coalesce(apeb.netpriceweek, apef.netpriceweek, itm.CostPriceStandard) * sle.quantity
sle_costpricequantity
label 'Kostprijs Artikelen'
, coalesce(por.suppliercode, sim.suppliercode)
por_suppliercode
, coalesce(por.suppliername, sim.supplierdescription)
por_suppliername
, por.ordernumber
por_ordernumber
, itm.code
sle_itemcode
label 'Artikelcode'
, itm.itemgroupcode
sle_itemgroupcode
, itm.costpricestandard
sle_costpricestandardcurrent
label 'Kostprijs Artikel Momenteel'
, apeb.netpriceweek
sle_costpriceapproximateb
label 'Kostprijs Artikel Historisch Terug'
, apef.netpriceweek
sle_costpriceapproximatef
label 'Kostprijs Artikel Historisch Vooruit'
, case
when apeb.netpriceweek is not null
then 'Vorige inkoop'
when apef.netpriceweek is not null
then 'Volgende inkoop'
else 'Standaard kostprijs'
end
herkomst
from sor@inmemorystorage sor
join SalesOrderLinesIncremental sle
on sle.orderid = sor.sor_orderid
and sle.LineNumber != 0
join itm@inmemorystorage itm
on itm.id = sle.item
left
outer
join exactonlinerest..purchaseorders por
on por.purchaseorderid = sle.purchaseorder
and itm.itemgroupcode != 'post'
left
outer
join sim@inmemorystorage sim
on sim.item = sle.item
left
outer
join approx_prices@inmemorystorage apeb
on apeb.itemcode = itm.code
and apeb.day_date = sor.sor_orderdate - to_number(to_char(sor.sor_orderdate, 'D'))
left
outer
join approx_prices@inmemorystorage apef
on apef.itemcode = itm.code
and apef.day_date = sor.sor_orderdate - to_number(to_char(sor.sor_orderdate, 'D')) + 7
;
create or replace table sorcost@inmemorystorage
as
select sor_division
, sor_orderid
, sor_ordernumber
, sor_orderdate
, sum(sle_costpricequantity)
sor_costpricequantity
label 'Kostprijs Artikelen'
, min(por_suppliercode)
por_suppliercode
label 'Eerste Leverancier Code'
, min(por_suppliername)
por_suppliername
label 'Eerste Leverancier Naam'
, min(por_ordernumber)
por_ordernumber
label 'Eerste Leverancier Bestelnummer'
from sle@inmemorystorage
group
by sor_division
, sor_orderid
, sor_ordernumber
, sor_orderdate
;
create or replace table sorall@inmemorystorage
as
select cst.sor_costpricequantity
, cst.por_suppliercode
, cst.por_suppliername
, cst.por_ordernumber
, sor.sor_amountfcexclvat - cst.sor_costpricequantity
margin
label 'Bruto Marge'
, case
when sor.sor_amountfcexclvat != 0
then ( sor.sor_amountfcexclvat - cst.sor_costpricequantity )
/ sor.sor_amountfcexclvat
else 1
end
margin_percentage
label 'Bruto Marge %'
, sor.*
from sor@inmemorystorage sor
left
outer
join sorcost@inmemorystorage cst
on cst.sor_orderid = sor.sor_orderid