Duplicate ID in the database - sql

I noticed in my database, some users have the same ID number (it seems to be a bug that didn't check if the id number was already taken for a deleted user).
There are hundreds of couples of users with the same ID number.
Through SQL I would like to update (adding a 0) to all those users who have a duplicate ID and are deleted.
I'm very familiar with the SQL language.
I found all the duplicate ID users using this query, but I am not sure how I should proceed.
SELECT ID, COUNT(*) As Num
FROM Users
GROUP BY ID
HAVING COUNT(ID) >= 2

If I understand correctly, you have some sort of "isdeleted" flag. Although I'm not sure that "adding a zero" is the best solution to your problem, the standard SQL for this would, based on your description, look something like this:
update t
set id = id || '0'
where isdeleted = 1 and
exists (select 1 from t t2 where t2.id = t.id and t2.isdeleted = 0);
This assumes that isdeleted is a number, with 0 for false and 1 for true. || is the standard SQL operator for string concatenation. Some databases have other mechanisms for string concatenation.

The query is for oracle, not sure what database are you using,
update users set id = id||0 where rowid not in
(select max(rowid ) from users group by id)
--and flag = 'Deleted Flag' -- uncomment the delete flag if you have in the table. If not just use same query a it is
;

Related

SQLite set records with matching checksums to same value if value is not set

I have a table that contains images: imageArchive
Images in the table are not unique
There is a checksum field that lets you know which images are identical
The record also contains a userID, but in many cases this field is NULL
How can I, if one record with a given checkSum has a userID, set all records with that checksum to the known userId?
I've gotten as far as:
select imageChksum from imageArchive
where userId != "NULL"
group by imagechksum
which gives me the set of known checksums that have userIds
and:
select * from imageArchive
where imagechksum in
(select imageChksum from imageArchive
where userId != "NULL"
group by imagechksum)
which gives me a list of targets to set. However I'm clueless as to how to set them all... probably simple? I'm pretty much self-taught in SQL and generally would do something like this in code but have a sense that I might be close
You can use window functions:
select imageChksum, max(userid) over(partition by imageChksum) as userid
from imageArchive
Note that if there are two different users assigned to the same checksum, the greatest id will be chosen.
If you wanted an update statement, I would recommend correlated subqueries:
update imageArchive
set userid = (select max(ia1.userid) from imageArchive ia1 where ia1.imageChksum = imageArchive.imageChksum)
where
userid is null
and exists (select 1 from imageArchive ia1 where ia1.imageChksum = imageArchive.imageChksum)

Randomly Select a Row with SQL in Access

I have a small access database with some tables. I am trying the code in the sql design within access. I just want to randomly select a record within a table.
I created a simple table called StateAbbreviation. It has two columns: ID and Abbreviation. ID is just an autonumber and Abbreviation are different abbreviations for states.
I saw this thread here. So I tried
SELECT Abbreviation
FROM STATEABBREVIATION
ORDER BY RAND()
LIMIT 1;
I get the error Syntax error (missing operator) in query expresion RAND() LIMIT 1. So I tired RANDOM() instead of RAND(). Same error.
None of the others worked either. What am I doing wrong? Thanks.
Ypercude provided a link that led me to the right answer below:
SELECT TOP 1 ABBREVIATION
FROM STATEABBREVIATION
ORDER BY RND(ID);
Note that for RND(), I believe that it has to be an integer value/variable.
You need both a variable and a time seed to not get the same sequence(s) each time you open Access and run the query - and to use Access SQL in Access:
SELECT TOP 1 Abbreviation
FROM STATEABBREVIATION
ORDER BY Rnd(-Timer()*[ID]);
where ID is the primary key of the table.
Please try this, it is helpful to you
It is possible by using a stored procedure and function, which I created it's have a extra column which you could be create in your table FLAG name and column all field value should be 0 Then it works
create Procedure proc_randomprimarykeynumber
as
declare #Primarykeyid int
select top 1
#Primarykeyid = u.ID
from
StateAbbreviation u
left join
StateAbbreviation v on u.ID = v.ID + 1
where
v.flag = 1
if(#Primarykeyid is null )
begin
UPDATE StateAbbreviation
SET flag = 0
UPDATE StateAbbreviation
SET flag = 1
WHERE ID IN (SELECT TOP 1 ID
FROM dbo.StateAbbreviation)
END
ELSE
BEGIN
UPDATE StateAbbreviation
SET flag = 0
UPDATE StateAbbreviation
SET flag = 1
WHERE ID IN (#Primarykeyid)
END
SET #Primarykeyid = 1
SELECT TOP 1
ID, Abbreviation
FROM
StateAbbreviation
WHERE
flag = 1
It is made in stored procedure run this and get serial wise primary key
exec proc_randomprimarykeynumber
Thanks and regard
Try this:
SELECT TOP 1 *
FROM tbl_name
ORDER BY NEWID()
Of course this may have performance considerations for large tables.

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;

Writing a single UPDATE statement that prevents duplicates

I've been trying for a few hours (probably more than I needed to) to figure out the best way to write an update sql query that will dissallow duplicates on the column I am updating.
Meaning, if TableA.ColA already has a name 'TEST1', then when I'm changing another record, then I simply can't pick a value for ColA to be 'TEST1'.
It's pretty easy to simply just separate the query into a select, and use a server layer code that would allow conditional logic:
SELECT ID, NAME FROM TABLEA WHERE NAME = 'TEST1'
IF TableA.recordcount > 0 then
UPDATE SET NAME = 'TEST1' WHERE ID = 1234
END IF
But I'm more interested to see if these two queries can be combined into a single query.
I am using Oracle to figure things out, but I'd love to see a SQL Server query as well. I figured a MERGE statement can work, but for obvious reasons you can't have the clause:
..etc.. WHEN NOT MATCHED UPDATE SET ..etc.. WHERE ID = 1234
AND you can't update a column if it's mentioned in the join (oracle limitation but not limited to SQL Server)
ALSO, I know you can put a constraint on a column that prevents duplicate values, but I'd be interested to see if there is such a query that can do this without using constraint.
Here is an example start-up attempt on my end just to see what I can come up with (explanations on it failed is not necessary):
ERROR: ORA-01732: data manipulation operation not legal on this view
UPDATE (
SELECT d.NAME, ch.NAME FROM (
SELECT 'test1' AS NAME, '2722' AS ID
FROM DUAL
) d
LEFT JOIN TABLEA a
ON UPPER(a.name) = UPPER(d.name)
)
SET a.name = 'test2'
WHERE a.name is null and a.id = d.id
I have tried merge, but just gave up thinking it's not possible. I've also considered not exists (but I'd have to be careful since I might accidentally update every other record that doesn't match a criteria)
It should be straightforward:
update personnel
set personnel_number = 'xyz'
where person_id = 1001
and not exists (select * from personnel where personnel_number = 'xyz');
If I understand correctly, you want to conditionally update a field, assuming the value is not found. The following query does this. It should work in both SQL Server and Oracle:
update table1
set name = 'Test1'
where (select count(*) from table1 where name = 'Test1') > 0 and
id = 1234

Fastest check if row exists in PostgreSQL

I have a bunch of rows that I need to insert into table, but these inserts are always done in batches. So I want to check if a single row from the batch exists in the table because then I know they all were inserted.
So its not a primary key check, but shouldn't matter too much. I would like to only check single row so count(*) probably isn't good, so its something like exists I guess.
But since I'm fairly new to PostgreSQL I'd rather ask people who know.
My batch contains rows with following structure:
userid | rightid | remaining_count
So if table contains any rows with provided userid it means they all are present there.
Use the EXISTS key word for TRUE / FALSE return:
select exists(select 1 from contact where id=12)
How about simply:
select 1 from tbl where userid = 123 limit 1;
where 123 is the userid of the batch that you're about to insert.
The above query will return either an empty set or a single row, depending on whether there are records with the given userid.
If this turns out to be too slow, you could look into creating an index on tbl.userid.
if even a single row from batch exists in table, in that case I
don't have to insert my rows because I know for sure they all were
inserted.
For this to remain true even if your program gets interrupted mid-batch, I'd recommend that you make sure you manage database transactions appropriately (i.e. that the entire batch gets inserted within a single transaction).
INSERT INTO target( userid, rightid, count )
SELECT userid, rightid, count
FROM batch
WHERE NOT EXISTS (
SELECT * FROM target t2, batch b2
WHERE t2.userid = b2.userid
-- ... other keyfields ...
)
;
BTW: if you want the whole batch to fail in case of a duplicate, then (given a primary key constraint)
INSERT INTO target( userid, rightid, count )
SELECT userid, rightid, count
FROM batch
;
will do exactly what you want: either it succeeds, or it fails.
If you think about the performace ,may be you can use "PERFORM" in a function just like this:
PERFORM 1 FROM skytf.test_2 WHERE id=i LIMIT 1;
IF FOUND THEN
RAISE NOTICE ' found record id=%', i;
ELSE
RAISE NOTICE ' not found record id=%', i;
END IF;
as #MikeM pointed out.
select exists(select 1 from contact where id=12)
with index on contact, it can usually reduce time cost to 1 ms.
CREATE INDEX index_contact on contact(id);
SELECT 1 FROM user_right where userid = ? LIMIT 1
If your resultset contains a row then you do not have to insert. Otherwise insert your records.
select true from tablename where condition limit 1;
I believe that this is the query that postgres uses for checking foreign keys.
In your case, you could do this in one go too:
insert into yourtable select $userid, $rightid, $count where not (select true from yourtable where userid = $userid limit 1);