Update using two tables in Ms access vba - sql

I want to update a table using numbers from another table, I want to do the following formla
Y-X(1)-(A1+A2+A3)
X is form table1 while Y,A1,A2,A3 from table2. The new record wil be updated in column X where the ID has only one of the records = 0
Table1
ID || X
-------------
1 || **0**
1 || 155
2 || 4
3 || 0
3 || 0
3 || 234
4 || 0
4 || 0
Table2
ID || Y || A1 || A2 || A3
--------------------------------------
1 || 228 || 1 || 3 || 4
2 || 112 || 6 || 7 || 7
3 || 4 || 22 || 1 || 0
4 || 78 || 76 || 6 || 2
from the above example tables the only column that will match the certiria is ID=1 where only one of them is 0 and the count = 2 so column X
where =0 will be updated ( X2= 228-155-(1+3+4))
Updated table1
ID || X
-------------
1 || **65**
1 || 155
2 || 4
3 || 0
3 || 0
3 || 234
4 || 0
4 || 0
My code is
Private Sub GET_TWO_INJLINE_EST()
DoCmd.SetWarnings False
DoCmd.RunSQL "UPDATE table1 I, table2 P" _
& " SET I.X = IIf(I.X = 0, DLookup(""P.Y-I.X-(P.A1 + P.A2 + P.A3)"" , " _
& " ""table1"", ""[ID]="" & [ID] & "" AND I.X <> 0""), I.X)" _
& " WHERE I.[ID] IN (SELECT I.[ID] FROM table1 I" _
& " GROUP BY I.[ID] HAVING (Count(I.[ID]) = 2)" _
& " AND (Min(I.ID) <> Max(I.X))" _
& " AND (Min(I.X) = 0 OR Max(I.X) = 0))" _
& " AND I.ID=P.ID"
DoCmd.SetWarnings True
End Sub
when I run it show me "Unknown" error.

Consider an UPDATE ... INNER JOIN query and reconciling your DLookUp as you attempt to pass I.X within the string expression. Furthermore, your subquery's Min() <> Max() equality does not compare to same X.
Finally, consider saving the update query as a stored Access query without concatenating in a VBA string which avoids the double quoting and forces you to check syntax error prior to saving. Plus, the database engine caches and pre-compiles for best execution plan.
SQL (save as Access stored query; see DMax inside larger expression)
UPDATE table1 I
INNER JOIN table2 P ON I.ID = P.ID
SET I.X = IIF(I.X=0, (P.Y - DMax("X", "table1", "ID=" & I.ID) - (P.A1+P.A2+P.A3)), I.X)
WHERE I.[ID] IN
(SELECT sub.[ID]
FROM table1 sub
GROUP BY sub.[ID]
HAVING (Count(sub.[ID]) = 2)
AND (Min(sub.X) <> Max(sub.X))
AND (Min(sub.X) = 0 OR Max(sub.X) = 0))
VBA
Private Sub GET_TWO_INJLINE_EST()
DoCmd.SetWarnings True
DoCmd.OpenQuery "mySavedUpdateQuery"
DoCmd.SetWarnings True
End Sub

try changing the second table1 I to table1 J and update all the references to the second table1
UPDATE table1 I, table2 P
Set I.X = IIf(I.X = 0,
DLookup(""P.Y-I.X-(P.A1 + P.A2 + P.A3)"",
""table1"",
""[ID]="" & [ID] & "" AND I.X <> 0""
),
I.X
)
WHERE I.[ID] IN (
SELECT J.[ID] FROM table1 J
GROUP BY J.[ID]
HAVING (Count(J.[ID]) = 2)
AND (Min(J.ID) <> Max(J.X))
AND (Min(J.X) = 0 OR Max(J.X) = 0))
AND J.ID=P.ID

Related

How to Update with subquery in PostgreSQL

I have a function in MS SQL Server just like this:
UPDATE r
SET
monthly =
(
SELECT SUM(-h.value_ini - h.purchase + h.sold + h.value_fin)
FROM hist_portfolio AS h
WHERE h.comp_id = r.comp_id
AND h.port_id = r.port_id
AND h.exte_id = r.cate_id
AND h.type_id = #type_rel_aux
AND h.hcar_day > #date_month_before
AND h.hcar_day <= #date_base
)
FROM #Month_Table r
WHERE type = 1;
and thats the result (after update):
Seq monthly
2 102471,34
1 -5129,46
3 -29841,23
4 0
But when I execute the same update in a fuction in PostgreSQL, all the rows get the same value:
UPDATE Month_Table
SET variacao_mes_rs = (
SELECT SUM(-h.value_ini - h.purchase + h.sold + h.value_fin)
FROM hist_portfolio AS h
WHERE h.comp_id = r.comp_id
AND h.port_id = r.port_id
AND h.exte_id = r.cate_id
AND h.type_id = v_type_rel_aux
AND h.hcar_day > v_date_month_before
AND h.hcar_day <= v_date_base) FROM Month_Table r WHERE type = 1;
Result (after update), all the same value of Seq 3:]
Seq monthly
1 -29841,23
2 -29841,23
3 -29841,23
4 -29841,23
I don't see the cause of the problem...
Does PostgreSQL have different rules on UPDATE?
Can anyone help me?
Remove the FROM clause from Postgres:
UPDATE Month_Table r
SET variacao_mes_rs = (
SELECT SUM(-h.value_ini - h.purchase + h.sold + h.value_fin)
FROM hist_portfolio AS h
WHERE h.comp_id = r.comp_id
AND h.port_id = r.port_id
AND h.exte_id = r.cate_id
AND h.type_id = v_type_rel_aux
AND h.hcar_day > v_date_month_before
AND h.hcar_day <= v_date_base)
WHERE type = 1;
The FROM clause in an UPDATE behaves differently in the two databases, as you have discovered.

Union causing Firebird 2.5 query to fail

This SQL (Firebird 2.5, Dialect 1) query works fine when I run it in Database Workbench, but it fails when I run it under IBO Console with:
count of column list and variable list do not match.
These two queries run successfully if I run them alone under IBO console, so I'm inferring that the problem is because of the "Union." The number and types of columns match for the two queries--both return string, smallint, string (IBO console regards this as a memo), string--so Union should be valid (and DB Workbench finds it so). Thinking that maybe the length of the data was different, I tried casting the third column as a VarChar(500) but that didn't help. Looking for ideas as to why this doesn't work since the part of our app that is executing the query is apparently choking on this in the same way that IBO Console is.
Select QBI.TXNID as ID,
Cast (1 as SmallInt) as TransactionType,
("Invoice " || QBI.REFNUMBER || ": $" || round(QBI.SUBTOTAL, 2) || " on " || QBI.TXNDATE || " for " || QBI.CUSTOMERREF_FULLNAME) as description,
case
when (QBI.CLASSREF_LISTID = "") then "Invoice has no class in Quickbooks"
else "Invoice class doesn't match any dept on job " || JA.JOBID
end as Problem
from QBINVOICE QBI
Join JOBACCOUNTINGID JA
on QBI.CUSTOMERREF_LISTID = JA.jobaccountingid
and QBI.SOURCEID = JA.SOURCEID
left Join CHARTOFACCOUNTS CA
on (CA.qblistid = QBI.CLASSREF_LISTID and CA.qbsourceID = QBI.SOURCEID)
and CA.CHARTACCOUNTTYPE = "SYSTEM"
and CA.CHARTFETCH = "Y"
left Join DEPARTMENTJOB DJ
on JA.JOBID = DJ.JobID
and DJ.departmentID = CA.DEPARTMENTID
where DJ.DEPARTMENTID is null
and QBI.TXNDATE >= "02/01/2017"
union all
select
QBELD.TXNLINEID as ID,
Cast (2 as SmallInt) as TransactionType,
QBB.VENDORREF_FULLNAME || " bill on " || QBB.TXNDATE || ": $" || round(QBELD.AMOUNT, 2) || " " || QBELD.ACCOUNTREF_FULLNAME || " expense" as description,
case
when (QBELD.CLASSREF_LISTID = "") then "Expense has no class in Quickbooks"
else "Expense class doesn't match any dept on job " || JA.JOBID
end as Problem
from QBTxnExpenseLineDetail QBELD
JOIN QBBILL QBB
on QBELD.TXNLINEID = QBB.TXNID
and QBELD.SOURCEID = QBB.SOURCEID
Join JOBACCOUNTINGID JA
on QBELD.CUSTOMERREF_LISTID = JA.jobaccountingid
and QBELD.SOURCEID = JA.SOURCEID
left Join CHARTOFACCOUNTS CA
on (CA.qblistid = QBELD.CLASSREF_LISTID and CA.qbsourceID = QBELD.SOURCEID)
and CA.CHARTACCOUNTTYPE = "SYSTEM"
and CA.CHARTFETCH = "Y"
left Join DEPARTMENTJOB DJ
on JA.JOBID = DJ.JobID
and DJ.departmentID = CA.DEPARTMENTID
where DJ.DEPARTMENTID is null
and QBB.TXNDATE >= "02/01/2017"

Update a boolean field as criteria using Count inside IF

I have 2 tables called t_task and t_task_details in MS Access
t_task has 3 columns: task_id, task_description, task_status (task_status column is Yes/No column while the rest are Short Text)
t_task_details also has 3 columns: task_id, task_date and done (done is also Yes/No)
Every task is linked to task_details via task_id.
I want update task_status to Yes / True if ALL task_details.done are Yes / True
I have tried this, but unfortunately it's not working:
UPDATE t_task
INNER JOIN t_task_details ON t_task.task_id = t_task_details.id
SET t_task.task_status = IIF(Count(t_task_details.done) = 0, True, False)
WHERE t_task_details.done = False
I think you can use a query like this:
UPDATE t_task
SET t_task.task_status = true
WHERE (SELECT COUNT(*)
FROM t_task_details
WHERE t_task_details.task_id = t_task.id) =
(SELECT COUNT(*)
FROM t_task_details
WHERE t_task_details.task_id = t_task.id
AND t_task_details.done = True)
I don't test it yet.
Note that this will update status of tasks that has no any details, If you want to remove them from update you can add this to the query:
...
AND EXISTS(SELECT 1 FROM t_task_details
WHERE t_task_details.task_id = t_task.id);
UPDATE :
If you want to update status to false for other records, I suggest you to use this query instead:
UPDATE t_task
SET t_task.task_status = IIF(
(SELECT COUNT(*)
FROM t_task_details
WHERE t_task_details.task_id = t_task.id) =
(SELECT COUNT(*)
FROM t_task_details
WHERE t_task_details.task_id = t_task.id
AND t_task_details.done = True), true, false)
WHERE EXISTS(SELECT 1 FROM t_task_details
WHERE t_task_details.task_id = t_task.id);
You can also use DCount and DSum:
UPDATE
t_task
SET
t_task.task_status =
(DCount("*", "t_task_details", "[task_id] = " & t_task.id & "") =
Abs(DSum("[done]","t_task_details", "[task_id] = " & t_task.id & "")))
If key is not numeric:
(DCount("*", "t_task_details", "[task_id] = '" & t_task.id & "'") =
Abs(DSum("[done]","t_task_details", "[task_id] = '" & t_task.id & "'")))

How to merge the Two column in vb.net?

I have 2 Data Table in Vb.Net
First Table Table1 Like
Accno || Name || databirth
100 || Hema || 10-may-1990
200 || Chand ||
300 || arul ||
Second Table table2 like
Accno databirth
100 10-may-1990
200 23-Aug-1990
300 5-Jan-1989
But I need Table1 like below Struture
Accno Name databirth
100 Hema 10-may-1990
200 Chand 23-Aug-1990
300 arul 5-Jan-1989
for i as byte = 0 to Table1.Rows.count-1
dim row as datarow = Table1.rows(i)
dim accno as integer = row("Accno")
dim dr() as datarow = Table2.Select("Accno=" & accno)
if dr.lenght>0 then
if not string.isnullorempty(row("databirth").tostring) then
row("databirth") = dr(0)("databirth")
end if
end if
next
next

Optimizing query in MS Access

I have created this query using MS Access:
SELECT
Abonentai.vardas AS name,
Abonentai.pavarde AS name1,
Abonentai.email AS email,
Abonentai.Telefonas AS phone1,
Abonentai.[Gimimo metai] AS birthdate,
"" AS phone2,
"" AS name2,
Last(Abonentai.Suma) AS paycost,
Abonentai.vardas & " " & Abonentai.pavarde AS fullname,
Last(AbonentaiD.Planas) AS Abonement_Code,
Last(AbonentaiD.Nuo) AS Abonement_StartDate,
Last(AbonentaiD.Iki) AS Abonement_ExpDate,
Last(AbonentaiD.Kartai) - (SELECT COUNT(StatistikaID) FROM Statistika WHERE Statistika.AbonentasID = Abonentai.AbonentasID AND Statistika.AtvykimoData > (SELECT Last(AbonentaiD.Nuo) FROM AbonentaiD WHERE AbonentaiD.AbonentasID = Statistika.AbonentasID)) AS MAXQUANTVISIT,
Abonentai.ANr AS CARDNO,
"22" AS CARDTYPE,
"" AS INFO
FROM Abonentai
LEFT JOIN AbonentaiD ON Abonentai.AbonentasID = AbonentaiD.AbonentasID
WHERE
(((AbonentaiD.Iki)>Date())) AND (((AbonentaiD.Kartai) Is Null)) OR (((AbonentaiD.Kartai) Is Not Null) AND ((Abonentai.GaliojimoData)>Date()))
GROUP BY
Abonentai.vardas,
Abonentai.pavarde,
Abonentai.email,
Abonentai.Telefonas,
Abonentai.[Gimimo metai],
Abonentai.vardas & " " & Abonentai.pavarde,
Abonentai.ANr,
Abonentai.AbonentasID,
Abonentai.RegistracijosData
HAVING
Last(AbonentaiD.Kartai) - (SELECT COUNT(StatistikaID) FROM Statistika WHERE Statistika.AbonentasID = Abonentai.AbonentasID AND Statistika.AtvykimoData > (SELECT Last(AbonentaiD.Nuo) FROM AbonentaiD WHERE AbonentaiD.AbonentasID = Statistika.AbonentasID)) > 0
OR
Last(AbonentaiD.Kartai) - (SELECT COUNT(StatistikaID) FROM Statistika WHERE Statistika.AbonentasID = Abonentai.AbonentasID AND Statistika.AtvykimoData > (SELECT Last(AbonentaiD.Nuo) FROM AbonentaiD WHERE AbonentaiD.AbonentasID = Statistika.AbonentasID)) IS NULL
;
But it takes alot of time to excecute it. Is there any way to reduse excecution time? I need every vaue that I am selecting.