Can't see all rows after sql update - sql

I am trying to Set the value of AmountOwed in my TransactionDetail table based on a formula using fields from TransactionDetail and SalesDetail tables. The inner Select query works and returns the expected value(s). The fields in use are of the following types:
TotalTender - money
PriceEntered - money
TaxRate - float
----- SQL Query -----
Update [POSDatabase].[dbo].[TransactionDetail]
Set AmountOwed =
(Select (TotalTender - (Select sum(PriceEntered+(PriceEntered*TaxRate*.01))
from POSDB.dbo.SalesDetail as Sales
where Sales.TransactionID = Trans.ID))
From POSDB.dbo.TransactionDetail as Trans
Where TransactionDetail.ID = Trans.ID)
Where ID = 4207
----- End SQL Query -----
When I run this query it says it affected 1 row, but when I try to view the table (Select * from Table), the query just spins. Oddly enough, if i scroll down, it has displayed all the records up to 5-6 less than the ID identified in this query.
I thought maybe I was having a data type mismatch, but same thing happens after a CONVERT or CAST has been done to change the result to a money type.
Any suggestions out there?

I am having a hard time following your query but I think something like this might work if I am understanding correctly.
;with s (TransactionID, total) as (
select TransactionID, sum(PriceEntered+(PriceEntered*TaxRate*.01))
from [POSDB].[dbo].[SalesDetail]
group by TransactionID
)
update td
set amountOwed = td.TotalTendered-s.total
from [POSDatabase].[dbo].[TransactionDetail] td
join s on td.id = s.TransactionID
where td.id = 4207

Related

Update table setting the value of a field to the result of a query

I have the following table(let's call it Sales) structure:
What I would like to do is to fill the field "SalesID" with values resulting from a query I have created in the same DB. This query reflects the table structure so I was thinking to connect the two using the ID.
Basically, I am trying with scripts of this forms:
UPDATE Sales
SET SalesID = ( SELECT SalesIDCalc FROM (SELECT Sales.ID, Sales.[Email Address], Sales.[Points], IIf([Points] >80,"Super","Normal") AS SalesIDCalc FROM Sales) AS q
WHERE Sales.ID = q.ID);
but I am nowhere near the solution. Do you have any idea on how to proceed?
EDIT: Now I get the Error 'Operation must use an updateable table'
I think you want UPDATE with a correlated subquery:
UPDATE Sales
SET SalesID = (SELECT SalesIDCalc
FROM (MyQuery) as q
WHERE Sales.ID = q.ID
);

SQL Update only updates one row

This code is only updating one row, why? It has to do with one of the sub-queries but I am not sure. I'm thinking the WHERE..IN in the UPDATE statement but I am not sure.
UPDATE [sde].[sy1].[Valve_evw]
SET [sde].[sy1].[Valve_evw].[MA]
= (SELECT [sde].[sy1].[Valve_Join_evw].[MC]
FROM [sde].[sy1].[Valve_Join_evw])
WHERE [sde].[sy1].[Valve_evw].[PrimaryKey]
IN (SELECT [sde].[sy1].[Valve_Join_evw].[PrimaryKey]
FROM [sde].[sy1].[Valve_Join_evw]
WHERE [sde].[sy1].[Valve_Join_evw].[MA]
!= [sde].[sy1].[Valve_Join_evw].[MC])
Context:
What I am trying to do is update the MA column in Valve_evw using the MC column in Valve_Join_evw. The PrimaryKey in Valve_evw references equivalent rows as the PrimaryKey in Valve_Join_evw. As in, a single row in Valve_Join_evw will have the same PrimaryKey as a single row in Valve_evw, thus that equivalency can be used to update the records in Valve_evw. Also the MA column is equivalent in both tables. [Note: The Valve_Join_evw table is created with ESRI mapping software using the spatial relationship between the Valve_evw and a separate table, this is how the duplicate rows exist]
I am using database views (hence the '_evw') in SQL Server with a default INSTEAD OF UPDATE trigger. This combination, views and trigger, prevents the use of table joins to do this update. I have also tried MERGE but that will not work either. Therefore I am stuck with the ANSI standard, hence the sub-queries. This script runs with no errors but it only updates a single row whereas there are about 9000 thousand rows in the tables.
The output message:
(1 row(s) affected)
(0 row(s) affected)
First of all let's reduce the eye hurting SQL to what it really is:
update sde.sy1.valve_evw
set ma = (select mc from sde.sy1.valve_join_evw)
where primarykey in (select primarykey from sde.sy1.valve_join_evw where ma <> mc)
WHERE clause
We look for all primarykey in valve_join_evw where a record's ma <> mc. We update all valve_evw records with such primarykey.
SET clause
For a record we want to update, we set ma to the value found with:
select mc from sde.sy1.valve_join_evw
But this query has no where clause, so what value does it select to fill the record's ma field? It selects all mc from valve_join_evw, so the DBMS probably picks one of these values arbitrarily. (It would be better, it raised an error.)
Conclusion
It is very easy to see which records the statement will update.
Which primarykey:
select primarykey from sde.sy1.valve_join_evw where ma <> mc
Which rows:
select *
from sde.sy1.valve_evw
where primarykey in (select primarykey from sde.sy1.valve_join_evw where ma <> mc)
As to the SET clause: Add a WHERE clause to your subquery that relates the record to select to the record to update (same ma? same primarykey?) E.g.:
set ma =
(
select mc
from sde.sy1.valve_join_evw vj
where vj.primarykey = valve_evw.primarykey
and vj.ma = valve_evw.ma
)
Hi there i recomend first to do the select statement and when you are ok with te records retrieved use the same where for the update statement
Here is what the final script looks like.
UPDATE [Valve_evw]
SET [Valve_evw].[MA] =
(
SELECT [Valve_Join_evw].[MC]
FROM [Valve_Join_evw]
WHERE[Valve_Join_evw].[PrimaryKey] = [Valve_evw].[PrimaryKey]
)
WHERE [Valve_evw].[PrimaryKey]
IN (
SELECT [Valve_Join_evw].[PrimaryKey]
FROM [Valve_Join_evw]
WHERE [Valve_Join_evw].[MA]
!= [Valve_Join_evw].[MC]
);

Update largest date, matching two fields

tables
Hi, I'm looking to update the last column in a blank table. Picture shows input and desired output. Trying to pick the largest date where workorder and state match.
I've tried a couple different codes:
UPDATE mytable
SET mytable.orderstartdate = MAX(table2.earliestdate)
FROM mytable as table2
WHERE (mytable.workorder = table2.workorder AND
mytable.state = table2.state)
;
"Syntax Error (missing operator) in query expression 'MAX(table2.earliestdate) FROM mytable as table2'."
UPDATE mytable
SET mytable.orderstartdate = (
SELECT max(earliestdate)
FROM mytable as table2
WHERE (mytable.workorder = table2.workorder AND
mytable.state = table2.state)
)
;
"Operation must use an updateable query"
Edit - click tables link for image.
Write PL/SQL Code.
First, select DISTINCT WorkOrder and State and capture in variables.
Now, Iterate the list and Write a query to get max date i.e. max(date) using work_order and State in where clause. Capture the
date.
Now, In the same loop write update query setting max(date) and workorder and State in where clause.
UPDATE table A
SET A.orderstartDate = (SELECT max(earliestdate)
FROM table B
WHERE A.WorkOrder = B.WorkOrder
GROUP BY WorkOrder)
not sure if access supports correlated subqueries but if it does...
and if not...
UPDATE table A
INNER JOIN (SELECT WorkOrder, max(OrderStartDate) MOSD
FROM Table B
GROUP BY WorkOrder) C
ON A.WorkOrder = C.workOrder
SET A.OrderStartDate = C.MOSD
Check database open mode, it may be locked for editing, or you may have no permission to to file.

Updating one table from another table

I have created a new table for my use , lets say t1 which has 8 columns in it. I have populated 3 columns through a procedure. Column 1 is name. Now I want to populate the 4th column for corresponding name. This would be update with where clause.
The scenario is I have created a query which has the result, calling that t2 which has name and total_amount. Now I want to populate total_amount into the 4th column of t1.
The approach that I'm right now following is looping through each name in t1 and finding its counter total_amount in t2(with clause) and updating the value in t1. But it is taking infinite time. First is because of looping in t1 , secondly the t2 is itself a query which is executing again and again.
Now, the actual task is much more complicated and I have just provided the crux of it. Please suggest me an approach which is fast.
create or replace procedure proc
is
temp_value number(18,2);
CURSOR total is
select name, age, sex from data_table where
{conditions};
/*Gives me name and age in 1st and 2nd column and likewise data in 3rd column */
begin
FOR temp IN total LOOP
with aa as (SELECT b.name,
NVL (SUM (c.amount), 0) as total_amount
FROM data_table2 b, data_table3 c
WHERE {joins and groub by}
)
/* This gives me total amount for corresponding name. There is no repetition of name */
select nvl(sum(total_amount),0) into temp_value from aa where name = temp.name;
update t1 set amount = temp_value where name = temp.name;
END LOOP;
END;
/
Cant add a comment to question, hence putting it here.
Per your example:
with aa as (SELECT b.name,
NVL (SUM (c.amount), 0) as total_amount
FROM data_table2 b, data_table3 c
WHERE {joins and groub by}
)
/* This gives me total amount for corresponding name. There is no repetition of name */
select nvl(sum(total_amount),0) into temp_value from aa where name = temp.name;
update t1 set amount = temp_value where name = temp.name;
In your with clause you you take some sum, and then populate the sum of those sum for all names in your cursor. Why cant you directly do:
SELECT SUM(NVL(total_amount, 0)) INTO temp_vale FROM
data_tabl1, data_tabl2, data_tabl3
WHERE
--JOIN CONDITIONS
AND data_tabl1.total)name = --data_tabl2/3.name
GROUP BY --clause;
Why I say this is, with clause is not always a good idea. If your 'with' has a huge data, then it will run forever. 'With' is used to take care of repetitive tables with small data being joined again and again.
Also for tuning purpose, try some hints.
Also, NVL(SUM..) why not SUM(NVL(total_amount, 0))?

Alternative to NOT IN()

I have a table with 14,028 rows from November 2012. I also have a table with 13,959 rows from March 2013. I am using a simple NOT IN() clause to see who has left:
select * from nov_2012 where id not in(select id from mar_2013)
This returned 396 rows and I never thought anything of it, until I went to analyze who left. When I pulled all the ids for the lost members and put them in a temp table (##lost), 32 of them were actually still in the mar_2013 table. I can pull them up when I search for their ids using the following:
select * from mar_2013 where id in(select id from ##lost)
I can't figure out what is going on. I will mention that the id field I created is an IDENTITY column. Could that have any effect on the matching using NOT IN? Is there a better way to check for missing rows between tables? I have also tried:
select a.* from nov_2012 a left join mar_2013 b on b.id = a.id where b.id is NULL
And received the same results.
This is how I created the identity field;
create table id_lookup( dateofcusttable date ,sin int ,sex varchar(12) ,scid int identity(777000,1))
insert into id_lookup (sin, sex) select distinct sin, sex from [Client Raw].dbo.cust20130331 where sin <> 0 order by sin, sex
This is how I added the scid into the march table:
select scid, rowno as custrowno
into scid_20130331
from [Client Raw].dbo.cust20130331 cust
left join id_lookup scid
on scid.sin = cust.sin
and scid.sex = cust.sex
update scid_20130331
set scid = custrowno where scid is NULL --for members who don't have more than one id or sin information is not available
drop table Account_Part2_Current
select a.*, scid
into Account_Part2_Current
from Account_Part1_Current a
left join scid_20130331 b
on b.custrowno = a.rowno_custdmd_cust
I then group all the information by the scid
I would prefer this form (and here's why):
SELECT a.id --, other columns
FROM dbo.nov_2012 AS a
WHERE NOT EXISTS (SELECT 1 FROM dbo.mar_2013 WHERE id = a.id);
However this should still give the same results as what you've tried, so I suspect there is something about the data model that you're not telling us - for example, is mar_2013.id nullable?
this is logically equivalent to not in and is faster than not in.
where yourfield in
(select afield
from somewhere
minus
select
thesamefield
where you want to exclude the record
)
It probably isn't as fast as using where not exists, as per Aaron's answer so you should only use it if not exists does not provide the results you want.