Can you run an UPDATE and WITH together? - sql

I am trying to run an update on a table, but get an error
ERROR: syntax error at or near "UPDATE"
The query is:
WITH
first_users AS (
select min(created_at) as first_at,
company_id as company_id
from users
group by company_id
)
UPDATE companies
SET first_seen_at = LEAST(first_seen_at,
(SELECT first_at FROM first_users WHERE id = first_users.company_id)
);
Can you not run UPDATEs and WITHs together? Seems weird.
My query is actually slightly more complex, which is why I am using the with syntax. When I run SELECT * FROM first_users instead of UPDATE, it works, so there's something wrong with the UPDATE keyword or something.

I would suggest changing this to an update . . . from in any case. There is no reason to update records that do not match. So:
update companies
set first_seen_at = u.first_at
from (select company_id, min(created_at) as first_at
from users
group by company_id
) u
where companies.id = u.company_id and
u.first_seen_at < companies.first_seen_at;
Postgres started supporting CTEs with updates in version 9.1 (http://www.postgresql.org/docs/9.1/static/sql-update.html vs http://www.postgresql.org/docs/9.0/static/sql-update.html). This method is better because it filters the rows before the update.

Try encapsulating the query qith BEGIN/END. I don't know about PostgreSql, but MsSql does not accept WITH without BEGIN/END...

Related

Delete query in SQL (Access) in conjuction with dependent data?

I know this is a very basic question but I am unable to get it done. Just started to learn more about databases. I have two tables: tblFoodAllowance and tblTravelDays.
tblFoodAllowance consists of ID, tripID, dateDay, costs.
tblTravelDay saves all days when I was on a business trip: ID, dateDay.
I am looking for a delete query in SQL to use in MS Access which does this: Delete all from tblFoodAllowance where tripID is xy (e.g. 1) and tblFoodAllowance.dateDay is not in the list of tblTravelDates. How can I achieve this?
I tried multiple things but either I got a syntax error or a wrong result. Thanks for your help.
I guess it is something like:
DELETE * FROM tblFoodAllowance WHERE tblFoodAllowance.tripID = [tripID] and ()
You can use delete:
delete from tblFoodAllowance
where tripID = #xy and
not exists (select 1
from tblTravelDates
where tblTravelDates.tripId = tblFoodAllowance.tripId and
tblTravelDates.dateDay = tblFoodAllowance.dateDay
);
Consider using not exists and a correlated subquery. It is a bit unclear exactly which colums connect the two tables, but the idea is:
delete from tblFoodAllowance
where
tripID = 1
and not exists (
select 1
from tblTravelDay
where tblTravelDay.dateDay = tblFoodAllowance.dateDay
)

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 Commands fails when using LIKE

I'm performing a bulk update on a column within a table. I need to change the current date from NULL to a past date.. Which I know works fine when performning against a single account. But when using a WILDCARD, this seems to fail.
Any ideas what my issue is, can I not use LIKE in subquery..
SET message.archived_at = (SELECT TO_CHAR(systimestamp-31, 'DD-MON-YY HH.MI.SS')
FROM dual)
WHERE EXISTS = (SELECT entity_id FROM user_info
WHERE UPPER(user_info.directory_auth_id) like 'USER%')
I have 10,000 records that I need to update..
I've changed to
UPDATE message
SET message.archived_at = (SELECT TO_CHAR(systimestamp-31, 'DD-MON-YY HH.MI.SS')
FROM dual)
WHERE EXISTS (SELECT entity_id FROM user_info
WHERE UPPER(directory_auth_id) like 'JLOADUSER1001%')
the SELECT query in the WHERE EXISTS section, when run by itself returns 10 users ID.. But when the whole query is run, this updates 1.8 million rows.. expected result is ~1500 rows..
LIKE clauses are allowed in Oracle subqueries and UPDATE statements. The line that seems erroneous is:
WHERE EXISTS = (SELECT entity_id FROM user_info
Use:
WHERE EXISTS (SELECT entity_id FROM user_info
instead

Oracle SQL update

I've tried searching for this particular topic here, but haven't found the answer... Anyway, my aim is to update table (let's call it t_item), specifically column owner_id with values depending on another table (t_item_geo which is in turn linked to t_geo).
I'm not entirely sure whether the syntax below is actually valid for update statements.
UPDATE t_item SET owner_id= 6993 WHERE t_item.owner_id in
(SELECT t_item.owner_id FROM
t_item,
t_item_geo,
t_geo
WHERE
t_item.id = t_item_geo.item_id and
t_item_geo.geo_id = t_geo.id and
t_item.owner_id in (SELECT id FROM t_user WHERE network_id='fffffff') and
t_geo.id in (SELECT id FROM t_geo WHERE full_name = 'yyyyyyy')
);
Anyway, my problem with this query is that it updates far more rows than it should - if I separate just the select statement Oracle returns ~750 rows but the udpate itself updates more than 4000 rows. It's almost as if the condition was completely ignored - which would point me to perhaps incorrect syntax.
I need to update specific value in the table based on the select from few other 'joined' tables. Hope it makes sense.
Thanks for any contribution!
UPDATE: sorry - maybe it wasn't clear from the question itself, but the correct number of edited items should be ~750 and not ~4000. Thanks!
try this
MERGE INTO t_item
USING
(
SELECT t_item.owner_id FROM
t_item,
t_item_geo,
t_geo,
t_item.rowid rowid_sub
WHERE
t_item.id = t_item_geo.item_id and
t_item_geo.geo_id = t_geo.id and
t_item.owner_id in (SELECT id FROM t_user WHERE network_id='fffffff') and
t_geo.id in (SELECT id FROM t_geo WHERE full_name = 'yyyyyyy')
) on (rowid = rowid_sub)
WHEN MATCHED THEN
UPDATE SET owner_id= 6993;

TRANSACT SQL - How to manually order/index a table based upon a select/where statement

I have sql puzzler today.
I have the following sql :
SELECT MemberId,
UnitId,
MaterialLevel,
MaterialText,
ProductPercentage,
ProductPriority
FROM tblWeights
ORDER BY MemberId, MaterialLevel, MaterialText, ProductPercentage DESC
Now, currently the ProductPriority is empty. What I would like to do is update this so that the first product, per level, per materialtext with the highest product percentage with "1", the second highest percentage with "2", etc, etc.
However, when the materialtext changes, this should reset itself and and start again at "1".
Can anyone think how I can do this?
Is there any reason you want productpriority explicitly stored in the database? Sorry if I've misunderstood your question but this sounds like it could be handled with a straight ROW_NUMBER in the output query.
You can use this for the initial update:
UPDATE tblWeights w1
SET ProductPriority = (
SELECT COUNT(*)
FROM tblWeights w2
WHERE w2.level = w1.level
AND w2.materialText = w1.materialText
AND w2.ProductPercentage >= w1.ProductPercentage
)
For the automatic reset, you should probably write a trigger that fires at the statement level after DELETE, UPDATE and INSERT. You can use a modified version of this statement, and only update the rows having the affected level,materialtext combination
CREATE TRIGGER aiud_tblWeights ON tblWeights
FOR INSERT, UPDATE, DELETE
AS
IF( UPDATE (Level) OR UPDATE (MaterialText) )
BEGIN
UPDATE tblWeights w1
SET ProductPriority = (
SELECT COUNT(*)
FROM tblWeights w2
WHERE w2.level = w1.level
AND w2.materialText = w1.materialText
AND w2.ProductPercentage >= w1.ProductPercentage
)
WHERE (w1.level, w1.materialText) IN (
SELECT level, materialText
FROM inserted
UNION ALL
SELECT level, materialText
FROM deleted
);
END;
I know its too late. but I found one answer when I was looking for similar questions for my help. see if helps someone else.
SQL query results to be displayed in the order of the manually provided values