Error: Update with select in MySQL 5 - mysql-error-1093

Next everybody, I'm trying to make a query (UPDATE) to debit credits in XX (value) of a company identified by script_id + cnpj.
Ie, the value will dynamically and identification of the company as well.
 
When I run the following error appears:
[Err] 1093 - You can not specify target table 'company' for update in FROM clause
 
Already googled, tried to optimize the code, but did not see another way to perform this query.
UPDATE empresa
SET saldo = saldo - (
SELECT
preco
FROM
preco_servico
WHERE
id = (
SELECT
emp2.idEscritorio
FROM
empresa AS emp2
WHERE
razao_social = (
SELECT
emp3.associacao
FROM
empresa AS emp3
WHERE
idEscritorio = (
SELECT
certidao_contratada.empresa_idEscritorio AS idEscritorio
FROM
certidao_contratada
INNER JOIN certidao_processada ON certidao_contratada.cnpj_idCnpj = certidao_processada.certidao_contratada_cnpj_idCnpj
WHERE
certidao_processada.certidao_contratada_scripts_idScript = 68 #script_id
AND certidao_processada.certidao_contratada_cnpj_idCnpj = '34.997.015/0001-98' #cnpj (da certidão)
ORDER BY
certidao_processada.dataHoraConcluido DESC
LIMIT 1
)
)
)
AND tipo_servico LIKE 'b%'
)
WHERE
emp1.idEscritorio = (
SELECT
certidao_contratada.empresa_idEscritorio AS idEscritorio
FROM
certidao_contratada
INNER JOIN certidao_processada ON certidao_contratada.cnpj_idCnpj = certidao_processada.certidao_contratada_cnpj_idCnpj
WHERE
certidao_processada.certidao_contratada_scripts_idScript = 68 #script_id
AND certidao_processada.certidao_contratada_cnpj_idCnpj = '34.997.015/0001-98' #cnpj (da certidão)
ORDER BY
certidao_processada.dataHoraConcluido DESC
LIMIT 1
);`

Related

How can I update a table using the following CROSS APPLY?

UPDATE ItemDim_DEV
set ActiveFlag = 0,
EndUTCDate = GETUTCDATE()
from (select i.SKU, i.itemname, i.category, i.CategoryInternalId, i.itemtype, i.IsActive, i.assetaccount, i.InternalId,
ni.sku,
ni.itemname,
ni.class_name,
ni.productclass,
ni.ItemType,
ni.isactive,
ni.assetaccount,
i.CalculatedHash, ni.hashid
from (
SELECT i.*
FROM itemDim_Dev i
WHERE i.SourceSystem = 'NetSuite'
--and InternalId = '1692'
) i
CROSS APPLY (
SELECT (CONVERT([binary](64),hashbytes('SHA2_512',
concat (ISNULL(im.TargetSKU, ni.sku), ni.itemname, pc.class_name, ni.productclass, ni.ItemType,
CAST(CASE WHEN ni.IsInactive = 'T' THEN 0 ELSE 1 END AS BIT ), ni.assetaccount)))) hashid,
ISNULL(im.TargetSKU, ni.sku) sku,
ni.itemname,
pc.class_name,
ni.productclass,
ni.ItemType,
CAST(CASE WHEN ni.IsInactive = 'T' THEN 0 ELSE 1 END AS BIT ) isactive, ni.assetaccount
FROM NetSuiteInventory ni
INNER JOIN Product_Class pc ON ni.productclass = pc.class_id
LEFT JOIN ItemMapping im ON ni.sku = im.SourceSKU
WHERE ni.ItemInternalId = CAST(i.InternalId as bigint)
and
(CONVERT([binary](64),hashbytes('SHA2_512',
concat (ISNULL(im.TargetSKU, ni.sku), ni.itemname, pc.class_name, ni.productclass, ni.ItemType,
CAST(CASE WHEN ni.IsInactive = 'T' THEN 0 ELSE 1 END AS BIT ), ni.assetaccount)))) = i.CalculatedHash
) ni
I understand that I can put a select after the from of the update but in the CROSS APPLY that is in the query starts with a select as in the second one, can you help me please.
Make a join to the target table
UPDATE A
SET XXX = YYY
FROM ItemDim_DEV A
JOIN (
--huge SELECT that I recommend you try to shorten in the next questions
CROSS APPLY (any secrets...)
) B ON A.PK = B.PK

How to use a column value in one of the select statement in the join in postgresql

I'm updating sitename as below. But then I need to utilize the levelindex from a in another query which is getting joined with the first query.
update billofquantity_temp a
set sitename = b.boqitemname
from (
select a.* from
(
select levelindex,productno,boqitemid,boqitemname,fileid from billofquantity_temp
where productno ='' and levelindex !='' //first query
) a
join
(
select distinct substring(levelindex,1,length(a.levelindex) lblindex from billofquantity_temp
where boqitemid !='' and levelindex !=''
and length(levelindex) > 2
) b on a.levelindex=b.lblindex // second query
) b
where a.levelindex=b.levelindex;
I need to use the a.levelindex in second query to get the substrings of the it's length. But this throws error invalid reference to FROM-clause entry for table "a"
Is there any other way to use the column from query 1 in 2 while joining them?
Update:
Based on kims answer, I could get the selection done but there is error syntax error at c.a.levelindex. There error is thrown even with c.levelindex.
A slight modification to the query made no errors but the intened update doesn't happen. Instead only one particular values is updated. Below is the updated query to remove errors
update billofquantity_temp d
set sitename = c.boqitemname
from (
select * from (
select levelindex, boqitemname from billofquantity_temp
where productno = '' and levelindex != '' -- first query
) a
join (
select distinct levelindex lblindex from billofquantity_temp
where boqitemid != '' and levelindex != '' and length(levelindex) > 2 ) b
on a.levelindex = substring(b.lblindex, 1, length(a.levelindex)) -- second query
) c
where d.levelindex = c.lblindex;
Move the computation of lblindex outside the sub-select to the on clause:
update billofquantity_temp d
set sitename = c.boqitemname
from (
select *
from (
select levelindex, boqitemname
from billofquantity_temp
where productno = '' and levelindex != '' -- first query
) a
join (
select distinct levelindex
from billofquantity_temp
where boqitemid != '' and levelindex != '' and length(levelindex) > 2
) b
on a.levelindex = substring(b.levelindex, 1, length(a.levelindex)) -- second query
) c
where d.levelindex = c.a.levelindex
;
I've also used c and d to avoid confusion from using a and b twice, added a missing ), and removed unused fields from select.

PostgreSQL - CTE slowing the query

I have a concern regarding the use of multiple WITH clauses in a query because
in some condition, it is slowing down the performance of the query like the below example,
So first WITH clause taking the 0.345 sec to fetch the 98948 records and second WITH clause taking the 13 sec to fetch the 68199 records even its less record as compare to first one so the only difference is that we have used the aggregate function in the second WITH clause to calculate the sum of charges.
Can anybody please help us to understand why the second query taking too much time.
1.This clause taking the 0.318 sec to fetch the 98948 record,
WITH delinquency_lease_details AS (
SELECT
dp.cid,
dp.id AS delinquency_policy_id,
p.id,
dp.threshold_amount,
dp.small_balance_amount,
dp.delinquency_threshold_type_id,
cl.id,
cl.primary_customer_id AS customer_id,
cl.lease_status_type_id,
cl.occupancy_type_id,
COALESCE( cl.building_name || ' - ' || cl.unit_number_cache, cl.building_name, cl.unit_number_cache ) AS unit_number, func_format_customer_name ( cl.name_first, cl.name_last, cl.company_name ) customer_name, cl.property_name, TZ.time_zone_name AS property_timezone
FROM
cached_leases cl
JOIN lease_details ld ON ( ld.cid = cl.cid AND ld.lease_id = cl.id )
JOIN delinquency_policies dp ON ( dp.cid = ld.cid AND ld.delinquency_policy_id = dp.id )
JOIN properties p ON ( p.cid = lp.cid AND p.id = lp.property_id )
JOIN time_zones TZ ON ( TZ.id = p.time_zone_id )
WHERE
cl.cid = 1111
AND cl.lease_status_type_id IN ( 4, 5 )
AND cl.occupancy_type_id IN ( 1, 2, 3, 4, 6, 9, 10, 11 )
AND cl.termination_list_type_id IS NULL
)
SELECT * FROM delinquency_lease_details;
2. This clause taking the 13 sec to fetch the 68199 records and if I just run the query without WITH clause then it is taking 0.564 seconds,
WITH delinquent_balance AS (
SELECT
dld.cid,
dld.id,
min( c.post_date ) AS min_post_date,
sum( c.transaction_amount_due ) AS delinquent_amount
FROM
cached_leases dld
JOIN charges at ON ( at.cid = dld.cid AND at.lease_id = dld.id AND c.is_temporary = FALSE AND c.is_deleted = FALSE )
JOIN charge_codes cc ON ( c.ar_code_id = cc.id AND c.cid = cc.cid AND cc.ledger_filter_id = 27 )
WHERE
dld.cid = 1111
AND ( ( c.transaction_amount_due > 0 AND c.post_date < CURRENT_DATE ) OR c.transaction_amount_due < 0 )
AND NOT EXISTS (
select
1
from
repayment_charges
WHERE
cid = c.cid
AND property_id = c.property_id
AND charge_id = c.id
AND is_active = true
)
GROUP BY
dld.cid,
dld.id
) select * from delinquent_balance;
As per this link, the WITH clause is the optimization barrier for Postgres database so it's really a cause then what we should use in place of WITH clause for complex queries because I have used the 10 WITH clauses in query and it is slowing down the performance of the query but out of that I have given two clauses only to get the some conclusion because the second clause taking more time as compared to another one.

How can I do calculations with previous defined columns in PostgreSQL?

I'm currently trying to calculate a column using previous declared columns. I think that would work in MySQL, but I'm unsure how do do that in PostgreSQL.
My Statement looks like this:
SELECT customerNumber, customerName, (
SELECT COALESCE(SUM(payments.amount), 0)
FROM payments
WHERE customers.customerNumber = payments.customerNumber
) as totalOfPaymentsMade,(
SELECT COALESCE(SUM(orderdetails.priceeach * orderdetails.quantityordered), 0)
FROM orders
LEFT JOIN orderdetails ON orderdetails.ordernumber = orders.ordernumber
WHERE customers.customerNumber = orders.customerNumber
) as totalValueOfAllOrdersMade, creditLimit, creditLimit + totalOfPaymentsMade - totalValueOfAllOrdersMade as amountOfAvailableCredit
FROM customers
ORDER BY customerNumber
I get this error message: column "totalofpaymentsmade" does not exist
LINE 11: ...lValueOfAllOrdersMade, creditLimit, creditLimit + totalOfPay...
Try this:
SELECT
*,
creditLimit + totalOfPaymentsMade - totalValueOfAllOrdersMade
as amountOfAvailableCredit
from
(
SELECT
customerNumber,
customerName,
creditLimit,
(
SELECT COALESCE(SUM(payments.amount), 0)
FROM payments
WHERE customers.customerNumber = payments.customerNumber
)
as totalOfPaymentsMade,
(
SELECT COALESCE(SUM(orderdetails.priceeach * orderdetails.quantityordered), 0)
FROM orders
LEFT JOIN orderdetails ON orderdetails.ordernumber = orders.ordernumber
WHERE customers.customerNumber = orders.customerNumber
)
as totalValueOfAllOrdersMade
FROM customers
) a
ORDER BY customerNumber

combine two sql sets of results while using TOP

I have these two queries and I want one set of results combining top 5 results for TP and top 5 results for LP.
I really do not know how to explain this more clearly, I have two sets of results, top 5 for LP and top 5 for TP and I would like to have a set of results Incident_TP, IncidentID_TP, IncidentHappenedDate_TP , IncidentNumber_TP , LossValue_TP , RecoveredValue_TP , TotalLoss_TP , Incident_LP, IncidentID_LP, IncidentHappenedDate_LP , IncidentNumber_LP , LossValue_LP , RecoveredValue_LP , TotalLoss_LP
DECLARE #IncidentFromDate_TP DATE = '2011-1-12'
DECLARE #IncidentToDate_TP DATE = '2012-1-12'
DECLARE #IncidentFromDate_LP DATE = '2010-1-12'
DECLARE #IncidentToDate_LP DATE = '2011-1-12'
SELECT TOP 5
Incident_TP = Incident_TP.IncidentID
, IncidentHappenedDate_TP = Incident_TP.IncidentHappenedDate
, IncidentNumber_TP = Incident_TP.IncidentNumber
, LossValue_TP = Incident_TP.TotalLoss
, RecoveredValue_TP = Incident_TP.TotalRecovered
, TotalLoss_TP = Incident_TP.CostOfIncident
FROM
Incident AS Incident_TP
INNER JOIN Site AS Site_TP ON Incident_TP.SiteID = Site_TP.SiteID
INNER JOIN Region AS Region_TP ON Site_TP.RegionID = Region_TP.RegionID
WHERE
Incident_TP.TotalLoss > 0.00
AND Incident_TP.IncidentHappenedDate BETWEEN #IncidentFromDate_TP AND #IncidentToDate_TP
ORDER BY
TotalLoss_TP DESC
, IncidentHappenedDate_TP DESC
SELECT TOP 5
Incident_LP = Incident_LP.IncidentID
, IncidentHappenedDate_LP = Incident_LP.IncidentHappenedDate
, IncidentNumber_LP = Incident_LP.IncidentNumber
, LossValue_LP = Incident_LP.TotalLoss
, RecoveredValue_LP = Incident_LP.TotalRecovered
, TotalLoss_LP = Incident_LP.CostOfIncident
FROM
Incident AS Incident_LP
INNER JOIN Site ON Incident_LP.SiteID = Site.SiteID
INNER JOIN Region ON Site.RegionID = Region.RegionID
WHERE
Incident_LP.TotalLoss > 0.00
AND Incident_LP.IncidentHappenedDate BETWEEN #IncidentFromDate_LP AND #IncidentToDate_TP
ORDER BY
TotalLoss_LP DESC
, IncidentHappenedDate_LP DESC
Many thanks
As Tim suggests you could union the sets together, For example:
DECLARE #IncidentFromDate_TP DATE = '2011-1-12';
DECLARE #IncidentToDate_TP DATE = '2012-1-12';
DECLARE #IncidentFromDate_LP DATE = '2010-1-12';
DECLARE #IncidentToDate_LP DATE = '2011-1-12';
WITH RawData
AS ( SELECT Incident_TP = Incident_TP.IncidentID ,
IncidentHappenedDate_TP = Incident_TP.IncidentHappenedDate ,
IncidentNumber_TP = Incident_TP.IncidentNumber ,
LossValue_TP = Incident_TP.TotalLoss ,
RecoveredValue_TP = Incident_TP.TotalRecovered ,
TotalLoss_TP = Incident_TP.CostOfIncident
FROM Incident AS Incident_TP
INNER JOIN Site AS Site_TP ON Incident_TP.SiteID = Site_TP.SiteID
INNER JOIN Region AS Region_TP ON Site_TP.RegionID = Region_TP.RegionID
WHERE Incident_TP.TotalLoss > 0.00
),
TopFiveSetA
AS ( SELECT TOP 5
*
FROM RawData
WHERE IncidentHappenedDate_TP BETWEEN #IncidentFromDate_TP
AND #IncidentToDate_TP
ORDER BY TotalLoss_TP DESC ,
IncidentHappenedDate_TP DESC
),
TopFiveSetB
AS ( SELECT TOP 5
*
FROM RawData
WHERE IncidentHappenedDate_TP BETWEEN #IncidentFromDate_LP
AND #IncidentToDate_LP
ORDER BY TotalLoss_TP DESC ,
IncidentHappenedDate_TP DESC
),
Merged
AS ( SELECT *
FROM TopFiveSetA
UNION ALL
SELECT *
FROM TopFiveSetB
)
SELECT *
FROM Merged