I am wondering if there is a way to delay Delete transactions in an SQR program? I am having an issue where I am deleting data from a table that has a trigger on it that inserts rows into another (Audit) table and the only key on the table that can be altered is a date/time stamp, but because these transactions are occuring at the exact same time (down to the hundreth of a second) it is causing duplicate insert errors on the sql trigger. I was hoping if there is a way to delay each row to be deleted in SQR that would be a good work-around to this issue. Thanks!
BEGIN-PROCEDURE DELETE-PSROLEUSER-ROLES
SHOW 'BEGINNING DELETE-PSROLEUSER-ROLES'
BEGIN-SQL
DELETE PSRO
FROM PSROLEUSER PSRO
INNER JOIN PS_GH_AD_X_WALK B ON B.OPRID = PSRO.ROLEUSER
INNER JOIN HRDEV01_FOR_BUDGET_MODULE.HRDEV92B.dbo.PS_JOB C ON C.EMPLID = B.GH_AD_EMPLID AND B.GH_AD_EMPLID <> ''
WHERE C.EFFDT =
(SELECT MAX(A_ED.EFFDT) FROM HRDEV01_FOR_BUDGET_MODULE.HRDEV92B.dbo.PS_JOB A_ED
WHERE C.EMPLID = A_ED.EMPLID
AND C.EMPL_RCD = A_ED.EMPL_RCD
AND A_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10))
AND C.ACTION = 'TER'
END-SQL
END-PROCEDURE DELETE-PSROLEUSER-ROLES
Please move all of the inner joins to the where clause for the delete. You probably don't intend to delete rows from these inner joined tables, some of which may return multiple rows for an emplid.
Related
I am trying to delete some duplicate records from mysql table but it was not working.
I am taking help of https://www.javatpoint.com/mysql-delete-duplicate-records
If I will try with example database which is given example it was working fine.
But in my table it was not working.
DELETE S1 FROM employee_attendance AS S1 INNER JOIN employee_attendance AS S2 WHERE S1.DbKey < S2.DbKey AND S1.DivisionDbKey = S2.DivisionDbKey AND S1.Date = S2.Date AND S1.Month = S2.Month AND S1.FinancialYearDbKey = S2.FinancialYearDbKey AND S1.EmployeeDbKey = S2.EmployeeDbKey AND S1.Attendance = S2.Attendance AND S1.InTime = S2.InTime AND S1.OutTime = S2.OutTime AND S1.EmployeeDbKey = 6798 AND S1.Month = '05' AND S1.FinancialYearDbKey = 5;
I am getting error
#1205 - Lock wait timeout exceeded; try restarting transaction
I have tried with another example https://www.geeksforgeeks.org/sql-query-to-delete-duplicate-rows/
DELETE FROM employee_attendance WHERE DbKey NOT IN (SELECT MAX(DbKey) FROM employee_attendance WHERE EmployeeDbKey = 6798 AND Month = '05' AND FinancialYearDbKey = '5' GROUP BY DivisionDbKey,Date,Month,FinancialYearDbKey,EmployeeDbKey,Attendance,InTime,OutTime)
I am getting same error.
#1205 - Lock wait timeout exceeded; try restarting transaction
Any suggestion will be appriciated. Thank you.
I personally think this is a bad practice. You should instead make a (empty) duplicate of the table employee_attendance then define a UNIQUE KEY on that new table that will prevent duplicate entries.
Consider these steps:
Create a duplicate table:
CREATE TABLE employee_attendance_new LIKE employee_attendance;
Add UNIQUE INDEX - now, this is just a simple example. You can add or reduce columns to the unique index but make sure that you drop the existing unique index first then only you re-create:
ALTER TABLE employee_attendance_new
ADD UNIQUE INDEX unq_idx(EmployeeDbKey, date, InTime, OutTime);
Insert the data into the new table using INSERT IGNORE..:
INSERT IGNORE INTO employee_attendance_new
SELECT * FROM employee_attendance;
Check and compare both table. If you're satisfied with the result, rename those tables:
RENAME TABLE employee_attendance TO employee_attendance_old;
RENAME TABLE employee_attendance_new TO employee_attendance;
Now you have the new table with no duplicates and the old table for reference or in case there are some data you need from it.
Fiddle example
I came across a situation where i have to delete a column from a table based on a condition from other table
Let me break it down to you!
There is a master table called MORTALITY (containing info regarding deceased individuals)
And another table called INC_MORTALITY (incremental mortality) table which is refreshed on a weekly basis
Note: Both the tables have similar format
So this week’s new records, containing both additional deceased individuals as well as updates of old data for previously delivered records. This is a single file with a column (OP_DIRECTIVE) specifying if it is an “add” or “delete” record.
Processing Weekly Files
To incorporate the weekly update file, we need to execute the following steps in order.
1. Delete rows in the master table which have a OP_DIRECTIVE = 'D' as the operation in the weekly update. For a given delete row, you should delete a single row in the master table which matches the delete record on all fields aside from the “D” operation column. Warning: please ensure you only delete, or mark as deleted, one record, even if more than one historical record fully matches this new delete record.
2. Add rows in the master table which appear in the “Add” file.
Upon completion of these steps, your master table should be the most up to date master of deaths.

(Note: THESE TABLES DOES NOT HAVE PRIMARY KEYS)
SO WHAT I TRIED:
DEL FROM MORTALITY MI
WHERE MI.DATA_SOURCE = INC_MORTALITY.DATA_SOURCE
AND MI.DD_IMP_FLAG = INC_MORTALITY.DD_IMP_FLAG
AND MI.DOB = INC_MORTALITY.DOB
AND MI.DOD = INC_MORTALITY.DOD
AND MI.DEATH_VERIFICATION = INC_MORTALITY.DEATH_VERIFICATION
AND MI.GENDER_PROBABILITY = INC_MORTALITY.GENDER_PROBABILITY
AND MI.GENDER = INC_MORTALITY.GENDER
AND MI.TOKEN_1 = INC_MORTALITY.TOKEN_1
AND MI.TOKEN_2 = INC_MORTALITY.TOKEN_2
AND MI.TOKEN_4 = INC_MORTALITY.TOKEN_4
AND MI.TOKEN_5 = INC_MORTALITY.TOKEN_5
AND MI.TOKEN_7 = INC_MORTALITY.TOKEN_7
AND MI.TOKEN_16 = INC_MORTALITY.TOKEN_16
AND MI.TOKEN_KEY = INC_MORTALITY.TOKEN_KEY
AND INC_MORTALITY.OP_DIRECTIVE = 'D'
The above Delete statement will delete all the rows satisfying the conditions, my requirement is to delete only one record even if more than one historical record fully matches this new delete record,
and if i include ROW NUMBER() stmt like below my DELETE stmt is not working
QUALIFY ROW_NUMBER() OVER (PARTITION BY MI.DATA_SOURCE,MI.DOB,MI.DOD
ORDER BY MI.DOD DESC ) = 1
Any suggestions on how to approach this scenario, Thanks!!
Approach to solution: Copy unmatched rows to a work table, then truncate the original table and replace with contents of the work table. One way to identify unmatched rows would be to tag each of the input rows in a set of duplicates with a unique number, something like this:
INSERT work_table SELECT MI.col1, MI.col2, ...
FROM
(SELECT M.*,
ROW_NUMBER() OVER (PARTITION BY <join cols> ORDER BY <some col(s)>) AS ROWNUM
FROM MORTALITY M) MI
LEFT JOIN
(SELECT I.*,
ROW_NUMBER() OVER (PARTITION BY <join cols> ORDER BY <some col(s)>) AS ROWNUM
FROM INC_MORTALITY I
WHERE OP_DIRECTIVE='D') INC
ON MI.join_col1 = INC.join_col1
AND MI.join_col2 = INC.join_col2
...
AND MI.ROWNUM = INC.ROWNUM
WHERE INC.ROWNUM IS NULL /* "anti-join" keeps only unmatched rows */
;
DELETE FROM MORTALITY;
INSERT MORTALITY SELECT * FROM work_table;
If INC_MORTALILTY never has duplicates, then you can eliminate numbering that relation and change the last join condition to MI.ROWNUM = 1 and use one of the other JOIN columns for the NULL check.
Edit
I would rather explicitly state my problem I'm facing rather than assuming the approach. There could be an easiest solution to my problem.
I need to select records by joining two different table based on the result from another table. And I have to use different joins based on the result from the first table.
If a particular record is present in the first table, I have two use inner join the first table whereas if it's not present, then I have to left join.
bool recordPresent = select exists (select * from firstTable where access_id = 13) as access
if (recordPresent)
results = select * from secondTable s left join firstTable f on f.access_id = s.access_id where f.access_id is null order by access_id
else
results = select * from secondTable s inner join firstTable f on f.access_id = s.access_id
I have the following columns in a SQLite DB.
id,ts,origin,product,bid,ask,nextts
1,2016-10-18 20:20:54.733,SourceA,Dow,1.09812,1.0982,
2,2016-10-18 20:20:55.093,SourceB,Oil,7010.5,7011.5,
3,2016-10-18 20:20:55.149,SourceA,Dow,18159.0,18161.0,
How can I populate the 'next timestamp' column (nextts) with the next timestamp for the same product (ts), from the same source? I've been trying the following, but I can't seem to put a subquery in an UPDATE statement.
UPDATE TEST a SET nextts = (select ts
from TEST b
where b.id> a.id and a.origin = b.origin and a.product = b.product
order by id asc limit 1);
If I call this, I can display it, but I haven't found a way of updating the value yet.
select a.*,
(select ts
from TEST b
where b.id> a.id and a.origin = b.origin and a.product = b.product
order by id asc limit 1) as nextts
from TEST a
order by origin, a.id;
The problem is that you're using table alias for table in UPDATE statement, which is not allowed. You can skip alias from there and use unaliased (but table-name prefixed) reference to its columns (while keeping aliased references for the SELECT), like this:
UPDATE TEST
SET nextts = (
SELECT b.ts
FROM TEST b
WHERE b.id > TEST.id AND
TEST.origin = b.origin AND
TEST.product = b.product
ORDER BY b.id ASC
LIMIT 1
);
Prefixing unaliased column references with the table name is necessary for SQLite to identify that you're referencing to unaliased table. Otherwise the id column whould be understood as the id from the closest[*] possible data source, in which case it's the aliased table (as b alias), while we're interested in the unaliased table, therefore we need to explicitly tell SQLite that.
[*] Closest data source is the one listed in the same query, or parent query, or parent's parent query, etc. SQLite is looking for the first data source (going from inner part to the outside) in the query hierarchy that defines this column.
Table: "user"
- Userid - Name -
(every userid is unique)
Table: "money spend"
- Userid - money spend -
(a userid may have several entries with different "money spend")
Now, I need the total sum of the money spend by a user.
To conclude, I need the following view:
- name - sum (money spend) -
Wich statement may give me this result?
You can use an aggregate function and group by:
select u.name, sum(ms.money)
from user u, money_spend ms
where u.userid = ms.userid
group by u.userid
Note that this here assumes that every user has at least 1 row in the money_spend table: http://www.sqlite.org/lang_aggfunc.html
Due to the way that aggregate functions work, you could set up the money_spend table with a 0 value for each user so you don't run into any issues :)
Because you might have users without any entry in table money_spend you need an outer join:
select n.name, sum(ms.money)
from user n
left outer join money_spend ms on (n.userid = ms.userid)
group by n.name
Edit: To be sure this all works I just tried this
create table user(userid, name);
insert into user values (1, 'user1');
insert into user values (2, 'user2');
insert into user values (3, 'user3');
create table moneyspend(userid, amount);
insert into moneyspend values (1,10);
insert into moneyspend values (1,20);
insert into moneyspend values (2,100);
select * from user;
select * from moneyspend;
select u.name, sum(m.amount)
from user u
left outer join moneyspend m on (u.userid = m.userid)
group by u.name;
drop table user;
drop table moneyspend;
The console output is the following (testSQLite is my test DB, testsql.sql is the above)
hols-Mac:div4 hol$ sqlite3 -init testsql.sql testSQLite
-- Loading resources from testsql.sql
1|user1
2|user2
3|user3
1|10
1|20
2|100
user1|30
user2|100
user3|
SQLite version 3.6.12
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>