Postgres Update column with another rows data - sql

Ok I have two tables
measures
attr_id, period, net_orders, ref_1 (key = attr_id,period)
and
policy
attr_id, lead_time
What I need to do is grab the 'net_orders' from measure at period (which is a date), Add the 'lead_time' and update the measure table 'ref_1' where period = period+lead
I currently have the select that gets me the data I need but I keep losing myself in my head when trying to figure out the where clauses.
SELECT
m.attr_id,
m.period,
m.net_orders,
p.lead_time,
DATE(m.period) + CAST(p.lead_time as INTEGER) as updateperiod
FROM
measures m
INNER JOIN policy p ON p.attr_id = m.attr_id
I am stuck with some of the following query - aka incomplete
UPDATE
measures m
SET
ref_1 = (SELECT m1.net_orders FROM measures m1
WHERE m1.attr_id = m.attr_id AND m1.period = m.period)
WHERE
attr_id = (SELECT m3.attr_id
FROM measures m3 WHERE m3.attr_id = m.attr_id
AND m3.period = m.period)
AND m.period = (SELECT DATE(m2.period) + CAST(p2.lead_time AS INTEGER)
FROM measures m2 INNER JOIN policy p2 ON p2.attr_id = m2.attr_id
WHERE m2.attr_id = m.attr_id AND m2.period = m.period)
EDIT
update measures m
set reference_1 = s.net_orders
from (
select
m.attribute_id, period, net_orders,
DATE(period) + CAST(lead_time as integer) as periodlevel
from
measures m
inner join policies p on p.attribute_id = m.attribute_id
) s
where
m.attribute_id = s.attribute_id
and m.period = s.periodlevel
This is the query that has ended up working. I was getting errors with first answer but looks like it is working now!

update measures m
set ref_1 = s.net_orders
from (
select
m.attr_id, period, net_orders,
period::date + lead_time::int period
from
measures m
inner join
policy using(attr_id)
) s
where
s.attr_id = m.attr_id
and s.period = m.period::date

Related

altering query in db2 to fix count from a join

I'm getting an aggregated count of records for orders and I'm getting the expected count on this basic query:
SELECT
count(*) as sales_180,
180/count(*) as velocity
FROM custgroup g
WHERE g.cstnoc = 10617
AND g.framec = 4847
AND g.covr1c = 1763
AND g.colr1c = 29
AND date(substr(g.extd1d,1,4)||'-'||substr(g.EXTD1d,5,2)||'-'||substr(g.EXTD1d,7,2) ) between current_Date - 180 DAY AND current_Date
But as soon as I add back in my joins and joined values then my count goes from 1 (which it should be) to over 200. All I need from these joins is the customer ID and the manager number. so even if my count is high, I'm basically just trying to say "for this cstnoc, give me the slsupr and xlsno"
How can I perform this below query without affecting the count? I only want my count (sales_180 and velocity) coming from the custgroup table based on my where clause, but I then just want one value of the xcstno and xslsno based on the cstnoc.
SELECT
count(*) as sales_180,
180/count(*) as velocity,
c.xslsno as CustID,
cr.slsupr as Manager
FROM custgroup g
inner join customers c
on g.cstnoc = c.xcstno
inner join managers cr
on c.xslsno = cr.xslsno
WHERE g.cstnoc = 10617
AND g.framec = 4847
AND g.covr1c = 1763
AND g.colr1c = 29
AND date(substr(g.extd1d,1,4)||'-'||substr(g.EXTD1d,5,2)||'-'||substr(g.EXTD1d,7,2) ) between current_Date - 180 DAY AND current_Date
GROUP BY c.xslsno, cr.slsupr
You are producing multiple rows when joining, so your count is now counting all the resulting rows with all that [unintended] multiplicity.
The solution? Use a table expression to pre-compute your count, and then you can join it to the other tables, as in:
select
g2.sales_180,
g2.velocity,
c.xslsno as CustID,
cr.slsupr as Manager
from customers c
join managers cr on c.xslsno = cr.xslsno
join ( -- here the Table Expression starts
SELECT
count(*) as sales_180,
180/count(*) as velocity
FROM custgroup g
WHERE g.cstnoc = 10617
AND g.framec = 4847
AND g.covr1c = 1763
AND g.colr1c = 29
AND date(substr(g.extd1d,1,4)||'-'||substr(g.EXTD1d,5,2)
||'-'||substr(g.EXTD1d,7,2) )
between current_Date - 180 DAY AND current_Date
) g2 on g2.cstnoc = c.xcstno
You can also use a Common Table Expression (CTE) that will produce the same result:
with g2 as (
SELECT
count(*) as sales_180,
180/count(*) as velocity
FROM custgroup g
WHERE g.cstnoc = 10617
AND g.framec = 4847
AND g.covr1c = 1763
AND g.colr1c = 29
AND date(substr(g.extd1d,1,4)||'-'||substr(g.EXTD1d,5,2)
||'-'||substr(g.EXTD1d,7,2) )
between current_Date - 180 DAY AND current_Date
)
select
g2.sales_180,
g2.velocity,
c.xslsno as CustID,
cr.slsupr as Manager
from customers c
join managers cr on c.xslsno = cr.xslsno
join g2 on g2.cstnoc = c.xcstno

How to use alias of a subquery to get the running total?

I have a UNION of 3 tables for calculating some balance and I need to get the running SUM of that balance but I can't use PARTITION OVER, because I must do it with a sql query that can work in Access.
My problem is that I cannot use JOIN on an alias subquery, it won't work.
How can I use alias in a JOIN to get the running total?
Or any other way to get the SUM that is not with PARTITION OVER, because it does not exist in Access.
This is my code so far:
SELECT korisnik_id, imePrezime, datum, Dug, Pot, (Dug - Pot) AS Balance
FROM (
SELECT korisnik_id, k.imePrezime, r.datum, SUM(IIF(u.jedinstven = 1, r.cena, k.kvadratura * r.cena)) AS Dug, '0' AS Pot
FROM Racun r
INNER JOIN Usluge u ON r.usluga_id = u.ID
INNER JOIN Korisnik k ON r.korisnik_id = k.ID
WHERE korisnik_id = 1
AND r.zgrada_id = 1
AND r.mesec = 1
AND r.godina = 2017
GROUP BY korisnik_id, k.imePrezime, r.datum
UNION ALL
SELECT korisnik_id, k.imePrezime, rp.datum, SUM(IIF(u.jedinstven = 1, rp.cena, k.kvadratura * rp.cena)) AS Dug, '0' AS Pot
FROM RacunP rp
INNER JOIN Usluge u ON rp.usluga_id = u.ID
INNER JOIN Korisnik k ON rp.korisnik_id = k.ID
WHERE korisnik_id = 1
AND rp.zgrada_id = 1
AND rp.mesec = 1
AND rp.godina = 2017
GROUP BY korisnik_id, k.imePrezime, rp.datum
UNION ALL
SELECT uu.korisnik_id, k.imePrezime, uu.datum, '0' AS Dug, SUM(uu.iznos) AS Pot
FROM UnosUplata uu
INNER JOIN Korisnik k ON uu.korisnik_id = k.ID
WHERE korisnik_id = 1
GROUP BY uu.korisnik_id, k.imePrezime, uu.datum
) AS a
ORDER BY korisnik_id
You can save a query (let's name it Query1) for the UNION of the 3 tables and then create another query that returns each row in the first query and calculates the sum of the rows that are before it (optionally checking that they are in the same group).
It should be something like this:
SELECT *, (
SELECT SUM(Value) FROM Query1 AS b
WHERE b.GroupNumber=a.GroupNumber
AND b.Position<=a.Position
) AS RunningSum
FROM Query1 AS a
However, it's more efficient to do that in the report.

DAX SUM outside current context

This is my current data model ->
part of data model
I need help in creating a measure.
The measure I want to create should show the overall capacity of the ships that had trips in a time interval, as well as be able to see the total capacity based on the room type.
I am interested in obtaining the DAX equivalent of :
SELECT SUM(sc.capacity)
FROM Reporting.Trips t
JOIN Reporting.Dates d ON d.DateId = t.DateId
JOIN Reporting.ShipCapacities sc on sc.ShipId = t.ShipId
WHERE d.FiscalYear= 2017 AND d.FiscalWeek=15
OR per type
SELECT SUM(sc.capacity)
FROM Reporting.Trips t
JOIN Reporting.Dates d ON d.DateId = t.DateId
JOIN Reporting.ShipCapacities sc on sc.ShipId = t.ShipId
WHERE d.FiscalYear= 2017 AND d.FiscalWeek=15 and sc.CabinTypeId = 11
I tried to define a measure in this manner:
Total Rooms:=CALCULATE ( SUM ( 'Ship Capacities'[Ship Capacity] ) )
I have seen that this outputs the T-SQL equivalent of:
SELECT SUM(Capacity)
FROM
(
SELECT DISTINCT sc.*
FROM Reporting.Trips t
JOIN Reporting.Dates d ON d.DateId = t.DateId
JOIN Reporting.ShipCapacities sc on sc.ShipId = t.ShipId
WHERE d.FiscalYear= 2017 AND d.FiscalWeek=15
) x
OR per type
SELECT SUM(Capacity)
FROM
(
SELECT DISTINCT sc.*
FROM Reporting.Trips t
JOIN Reporting.Dates d ON d.DateId = t.DateId
JOIN Reporting.ShipCapacities sc on sc.ShipId = t.ShipId
WHERE d.FiscalYear= 2017 AND d.FiscalWeek=15 and sc.CabinTypeId = 11
) x
These are the query results ->Query results
Thanks.
This is the final measure that worked for me:
Total Rooms:=CALCULATE (
SUMX (
'Ship Capacities',
'Ship Capacities'[Ship Capacity]
* COUNTROWS ( FILTER ( Trips, AND( Trips[Sailed] = TRUE (),Trips[ShipId] = 'Ship Capacities'[ShipId] ) ))
)
)
Notice the COUNTROWS.
In the case of a many to one, then a one to many relation, it did not iterate (but previously I used SUM and not SUMX).
I found it unusual that I have to mention the relation between the many to many tables.
Otherwise it does not work.

Query to return all values in a specific table column

The query below returns a somatory of all groups in the year.
How can I return all groups that exists in IND_GRUPO but grouped by the month, if doesn't exist the group for the current month, the name should appear, but the somatory will be 0. All joins should be kept.
SELECT SUM(p.valor), c.nm_grupo, c.cd_grupo, YEAR(p.dt_emissao)
FROM ind_receita p
JOIN ind_equipto o ON p.cd_equipto = o.cd_equipto
JOIN ind_grupo c ON o.cd_grupo = c.cd_grupo
WHERE YEAR(p.dt_emissao) = YEAR(GETDATE())
GROUP BY YEAR(p.dt_emissao), c.nm_grupo, c.cd_grupo
ORDER BY 1 DESC
Try this:
SELECT c.nm_grupo, c.cd_grupo, YEAR(GETDATE()),
(SELECT SUM(p.valor)
FROM ind_receita p
JOIN ind_equipto o ON p.cd_equipto = o.cd_equipto
JOIN ind_grupo c2 ON o.cd_grupo = c2.cd_grupo
WHERE c2.cd_grupo = c.cd_grupo
AND YEAR(p.dt_emissao) = YEAR(GETDATE())) AS valor
FROM ind_grupo c

Update table with rolling average from itself

I'm trying to update a temp table with a rolling average calculation (MS Access 2010.)
As a select query, this works to calculate a 3 month rolling average but is slow so I'd rather have the values stored and updated only when necessary:
SELECT tempQORDistGrouped.Type, tempQORDistGrouped.Supplier, tempQORDistGrouped.DepBkMo, tempQORDistGrouped.Amt, tempQORDistGrouped.Brands, tempQORDistGrouped.T2, tempQORDistGrouped.Brand, (select avg(rolavg.Amt) from tempQORDistGrouped as rolavg
where rolavg.Type = tempQORDistGrouped.Type
and rolavg.Supplier = tempQORDistGrouped.Supplier
and rolavg.Brands = tempQORDistGrouped.Brands
and rolavg.Brand = tempQORDistGrouped.Brand
and rolavg.DepBkMo between dateadd("m",-2,tempQORDistGrouped.DepBkMo) and tempQORDistGrouped.depbkmo) AS AvgAmt
FROM tempQORDistGrouped;
I've tried the update query below but I think my inner join syntax is bad as it won't recognize x1.Type as a valid field (do I need to include these as part of the inner join fields rather than in the where clause??):
UPDATE tempQORDistGrouped AS x1
INNER JOIN (SELECT itmID, avg(Amt) AS RolAvg
FROM tempQORDistGrouped
WHERE tempQORDistGrouped.Type = x1.Type
AND tempQORDistGrouped.Brand = x1.Brand
AND tempQORDistGrouped.Brands = x1.Brands
AND tempQORDistGrouped.T2 = x1.T2
AND tempQORDistGrouped.DepBkMo between dateadd("m",-2,x1.DepBkMo) and x1.DepBkMo
GROUP BY itmID
) AS x2
ON x1.itmID = x2.itmID
SET x1.3MonthRollingAmt = x2.RolAvg;
Cheers
Untested but should work.
I am doing a column level query to calculated the AVG and then mapping it back to the rest of the columns
Try this:
UPDATE tempQORDistGrouped AS x1
INNER JOIN (
SELECT itmID
, (
SELECT avg(Amt) amt
FROM tempQORDistGrouped x4
WHERE x4.Type = x3.Type
AND x4.Brand = x3.Brand
AND x4.Brands = x3.Brands
AND x4.T2 = x3.T2
AND x4.DepBkMo BETWEEN dateadd("m", - 2, x3.DepBkMo) AND x3.DepBkMo
) AS RolAvg
, x3.Brand
, x3.Brands
, x3.DepBkMo
, x3.T2
FROM tempQORDistGrouped x3
) AS x2
ON x1.itmID = x2.itmID
AND x1.Brand = x2.Brand
AND x1.Brands = x2.Brands
AND x1.T2 = x2.T2
AND x1.DepBkMo BETWEEN dateadd("m", - 2, x2.DepBkMo) AND x2.DepBkMo
SET x1.3MonthRollingAmt = x2.RolAvg;