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

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
)

Related

Can you force SQL Server to send the WHERE clause to Linked Server?

I'm trying to determine if a table in my SQL Server 2012 database has any records that don't exist in a table that's on a linked Oracle 11g database.
I tried to do this with the following:
select 1
from my_order_table ord
where not exists (select 1
from LINK_ORA..[SCHEMA1].[ORDERS]
where doc_id = ord.document_id)
and document_id = 'N2324JKL3511'
The issue is that it never completes because the ORDERS table on the linked server has about 100 million rows and as per the explain plan on SQL Server, it is trying to pull back the entire ORDERS table from the linked server and then apply the WHERE clause.
As per the explain plan, it views the remote table as having an estimated 10000 rows - I assume that's some kind of default if it is unable to get statistics..?
Even running something as simple as this:
select 1 from LINK_ORA..[SCHEMA1].[ORDERS] where doc_id = 'N2324JKL3511'
causes SQL Server to not send the WHERE clause and the query never completes.
I tried to use OPENQUERY however it won't let me add the doc_id to concatenate into the WHERE clause of the query string.
Then I tried to build a select FROM OPENQUERY string in a function but I can't use sp_executesql in a function to run it.
Any help is greatly appreciated.
I think this would logically work for you, but it may take too long as well.
SELECT sql_ord.*
FROM my_order_table sql_ord
LEFT JOIN LINK_ORA..[SCHEMA1].[ORDERS] ora_ord ON sql_ord.document_id = ora_ord.doc_id
WHERE sql_ord.document_id = 'N2324JKL3511'
AND ora_ord.doc_id IS NULL
Since you have problem with something as simple as select 1 from LINK_ORA..[SCHEMA1].[ORDERS] where doc_id = 'N2324JKL3511' have you try to create a table on the remote server that will hold the doc_id that you want to look at. So your SELECT will include a table that contain only 1 row. I'm just not sure about the INSERT since I can't test it for now. I'm assuming that everything will be done on the remote server.
So something like :
CREATE TABLE LINK_ORA..[SCHEMA1].linked_server_doc_id (
doc_id nvarchar(12));
INSERT INTO LINK_ORA..[SCHEMA1].linked_server_doc_id (doc_id)
SELECT doc_id
FROM LINK_ORA..[SCHEMA1].[ORDERS] WHERE doc_id = 'N2324JKL3511';
select 1
from my_order_table ord
where not exists (select 1
from LINK_ORA..[SCHEMA1].[linked_server_doc_id]
where doc_id = ord.document_id)
and document_id = 'N2324JKL3511';
DROP TABLE LINK_ORA..[SCHEMA1].linked_server_doc_id

Can you run an UPDATE and WITH together?

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...

SQL Update with select MIN from specific group in one table

Im really new to SQL. I searched for an answer that would match my requirements AND I would understand what has been done- I failed obv. So here it goes:
I am making a programm that would keep data for marathon tournament. So I have a table StageResults with columns: StageNo ParticipantNumber ParticipantGroup Time(as in distance time in full sec's thus int) and Points
An example would look like:
- 1|01|M21|500|X
- 1|22|M21|550|X
- 1|45|M21|530|X
- 1|47|F09|600|X
- 1|09|F09|630|X
- 2|01|M21|515|X
- 2|45|M21|520|X
So I want the fastest member of each group in each stage to get 1000 points. In the back of my head I feel, that I could just write 1 single query for this, I tried for several hours.
Best that I have right now is this:
SELECT c1.ParticipantNumber, c1.ParticipantGroup, c1.Time
FROM StageResults AS c1
LEFT JOIN StageResults AS c2
ON c1.StageNo = c2.StageNo
AND c1.ParticipantGroup = c2.ParticipantGroup
AND c1.Time < c2.Time;
I used this under INSERT statement. No syntax errors but error, that I am trying to insert a duplicate primary key. I think this can be solved by adding GROUP BY statement. So I havent really tested this.
I would ultimately like to set 1000 points for fastest participant in each run(stage) and each group(I mean it should happen automatically). And then based on the fastest guy, calculate points for all other guys.(But thats later and if i figure out how to add these 1k pts, I think ill manage)
So I have to add this logic inside UPDATE statement. I am not able to. Im just lost.
Any advice is welcome. Maybe im thinking in the wrong direction completely on how to do this.
Any help will be much appreciated.
The query that identifies the rows might look like this:
select t.*
from table t
where not exists (select 1
from table t2
where t2.ParticipantGroup = t.ParticipantGroup and
t2.StageNo = t.StageNo and
t2.time < t.time
);
The question is then how you turn this into an update. For MySQL, you would do:
update table StageResults sr join
(select t.*
from table t
where not exists (select 1
from table t2
where t2.ParticipantGroup = t.ParticipantGroup and
t2.StageNo = t.StageNo and
t2.time < t.time
)
) toupdate
on toupdate.ParticpantNumber = sr.ParticpantNumber
set sr.points = sr.points + 1000;
The syntax for SQL Server would be a bit different, but your question is tagged MySQL.
EDIT:
For SQL Server:
with toupdate as (select t.*
from table t
where not exists (select 1
from table t2
where t2.ParticipantGroup = t.ParticipantGroup and
t2.StageNo = t.StageNo and
t2.time < t.time
)
)
update toupdate
set points = points + 1000;

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;

Sql Server CE can I delete TOP or only 1 record from table that matches my query

select Top(1)* from TableName Where columnName=value
selects only the first row just fine. However if I change the select to a delete I get an error and can't figure out how to write a query to delete only 1 record that matches my query from the db.
I'm wondering if anybody out there smarter than I knows if or how this can be done in SQL CE.
Did you try something like this?
DELETE TableName where IdColumn In ( select Top(1) IdColumn from TableName Where columnName=valuev)
I don't know specifically as I'm at home, but SQL CE is deliberately restricted in what it can do. One reason for this is that it is 'always' running locally to the process referencing it.
What means is that it is Expected that the other process is expected to handle much of the logic that may otherwise be encapsulated in the SQL Server. This often results in firing several queries at the SQL CE instance, where you may be more accustomed to firing off one.
In this case, you could do it with two queries...
1) A query to identify the record that you want to delete
2) Use that Identifier in another query to do the actual delete
You could also try using SET ROWCOUNT 1 to limit the DELETE to just 1 row. But again, I don't know if that works in CE.
You can use CTE such as
;with myTopRow(rowID)
(
select Top 1 rowID from TableName Where columnName=value
)
delete from TableName inner join myTopRow on TableName.rowID = myTopRow.rowID
Shouldn't it be rather :
DELETE FROM TableName WHERE columnName=value ORDER BY columnName LIMIT 1;
IMHO, the table logically has NO order by itself. It has it physically, but you can't rely on it. So, you HAVE to set the order in which you want to delete the first row.
The following code will delete only first row
Dim mySqlCommondDelete As String = "DELETE BOOK_ID, MemberID FROM (SELECT TOP 1 * FROM ISSUE_BOOK) where BOOK_ID = Val(" & deleteBook & ") and MemberID = Val(" & msk & ")"