compare values of same column on same table - mysql

This has got to be a simple question, just brain-dumbing right now...
I've got one table, called 'foo'. It's got two columns, 'id' and 'username'.
The id is unique, but some of the usernames reference the same user; just one has a prefix on the username of 'xx_'.
ex:
ID USERNAME
1 bob
2 sam
3 xx_bob
How can I figure out which of the users have a counterpart with the 'xx_' prefix? And then which ones do not?

select * from foo where username
IN (select replace(username, 'xx_', '') from foo where username like 'xx_%')
What this does is compares the entire table against a sub list which is generated by the sub-query after the IN verb.
To do the opposite you can simply use a NOT IN in place of the IN.
NOTE: This is a t-sql (MS SQL 2005) query, should be similar in MySQL

This will give you the id's of both rows:
select * from foo a1 join foo a2 on (a2.username=concat('xx_',a1.username));

If you want every rows that isn't a duplicate, with the duplicate_id:
SELECT foo.*, f2.id AS duplicate_id FORM foo
LEFT OUTER JOIN foo AS f2 ON ( f2.username = concat( 'xx_', foo.username ) )
WHERE foo.id NOT LIKE 'xx_%'

Related

Find an entry in sql dependent on other entries in the table

How can I return all entries in a table that contain a string in a given column if the same string is also present in the same column with a given suffix ?
So for example, given the suffix 'bar', and the following table:
id A
1 foo1
2 foo2
3 foo1bar
I want to return the the first entry, because there's another entry (the third one) which has the same value when the suffix is appended.
SELECT t1.*
FROM table t1
JOIN table t2 ON CONCAT(t1.column, 'bar') = t2.column
I would suggest using exists:
select t.*
from t
where exists (select 1
from t t2
where t2.a = concat(t.a, 'bar')
);
I recommend this specifically over a join to avoid returning duplicate values, in the event that multiple rows match the conditions.

How could I get a list of unique records from below duplicated records by ignoring first two characters?

Here is the rule:
When comparing userId, only search userId starting with 'AB' and its matching duplicates (except 'AB'). Then get a list of "unique userId" by only returning above duplicated userId that is having 'AB' at the beginning.
For returned duplicated string starting with 'AB', we need to make sure there is "duplicate"; otherwise, we should not return 0 record
I know it sounds confusing, please see example below:
Table UserName with ten records, and its userId fields (10 records) are:
ABC1234
C1234
C12345
BC12345
BBC1234
ABF1235
F1235
ABY1236
BCD3456
D3456
Desired Result after running query:
ABC1234
ABF1235
Please note: Although ABY1236 starts with 'AB', this record should not be returned in output, since it doesn't have a "duplicate" match like Y1236 (ignoring first two character, 'AB').
I have a sample query below, but it only returned duplicated record NOT starting with 'AB', also it will return ABY1236.
SELECT distinct substr(userId , -(length(userID)-2))
from UserName where userId like 'AB%';
Thanks for the help!
You can use EXISTS to check if there is a userId that is equal to the right part of "AB.." starting from the 3d char:
select u.userId from UserName u
where
u.userId like 'AB_%'
and
exists (
select 1 from UserName where userId = substr(u.userId, 3)
)
You could try using a selct join for check only the matching result
SELECT substr(a.userId , -(length(a.userID)-2))
from UserName a
INNER JOIN UserName b ON a.substr(a.userId , -(length(a.userID)-2)) = b.UserId
AND userId like 'AB%'

return values of table 1 based on single column in table 2

I have 3 tables that I am using and need to make a query to return data from one table based on the value of a single column in the second table.
tbl_user
ID
login
pass
active
mscID
tbl_master
ID
name
training_date
MSCUnit
Active
tbl_msc
mscID
mscName
my current SQL statement:
SELECT
tbl_master.ID,
tbl_master.name,
tbl_master.training_date,
tbl_master.MSCUnit,
tbl_master.active,
tbl_user.mscID
FROM
tbl_master,
tbl_user
WHERE
tbl_master.active = 1 AND tbl_master.MSCUnit = tbl_user.mscID
The values stored in tbl_msc.mscID is a varchar(11) and it contains a string similar to A00 or A19. This is also the Primary key in the table.
The values stored in tbl_user.mscID matches that of tbl_msc.mscID. The values stored in tbl_master.UnitMSC also matches that of tbl_msc.mscID.
My goal is to return all records from tbl_master where the currently logged in user has the same mscID. The problem I am having is the statement returns all records in tbl_master.
I have tried several different join statements and for some reason, I cannot get this to filter correctly.
I am missing something. Any assistance in the SQL statement would be appreciated.
Thanks,
Will
You should be writing this using joins. I don't know how you know who the current user is, but the idea is to join the three tables together:
SELECT m.ID, m.name, m.training_date, m.MSCUnit, m.active,
u.mscID
FROM tbl_master m JOIN
tbl_user u
ON m.MSCUnit = u.mscID JOIN
tbl_msc msc
ON msc.mscID = u.msc_ID
WHERE m.active = 1 AND msc.mscName = ?;
Notice the use of proper, explicit, standard JOIN syntax and table aliases.
Select a.*, b.userid from
table_master a, table_user b where
a.mscunit in (select mscid from
table_user where active=1)
This should point you in the right direction.

Get a list of ids not present in a table

I have a list of ids, and I want to query a mysql table for ids not present in the table.
e.g.
list_of_ids = [1,2,4]
mysql table
id
1
3
5
6
..
Query should return [2,4] because those are the ids not in the table
since we cant view ur code i can only work on asumption
Try this anyway
SELECT id FROM list_of_ids
WHERE id NOT IN (SELECT id
FROM table)
I hope this helps
There is a horrible text-based hack:
SELECT
substr(result,2,length(result)-2) AS notmatched
FROM (
SELECT
#set:=replace(#set,concat(',',id,','),',') AS result
FROM (
select #set:=concat(',',
'1,2,4' -- your list here
,',')
) AS setinit,
tablename --Your tablename here
) AS innerview
ORDER BY LENGTH(result)
LIMIT 1;
If you represent your ids as a derived table, then you can do this directly in SQL:
select list.val
from (select 1 as val union all
select 2 union all
select 4
) list left outer join
t
on t.id = list.val
where t.id is null;
SQL doesn't really have a "list" type, so your question is ambiguous. If you mean a comma separated string, then a text hack might work. If you mean a table, then something like this might work. If you are constructing the SQL statement, I would advise you to go down this route, because it should be more efficient.

sql query for deleting rows with NOT IN using 2 columns

I have a table with a composite key composed of 2 columns, say Name and ID. I have some service that gets me the keys (name, id combination) of the rows to keep, the rest i need to delete. If it was with only 1 row , I could use
delete from table_name where name not in (list_of_valid_names)
but how do I make the query so that I can say something like
name not in (valid_names) and id not in(valid_ids)
// this wont work since they separately dont identity a unique record or will it?
Use mysql's special "multiple value" in syntax:
delete from table_name
where (name, id) not in (select name, id from some_table where some_condition);
If your list is a literal list, you can still use this approach:
delete from table_name
where (name, id) not in (select 'john', 1 union select 'sally', 2);
Actually, no I retract my comment about needing special juice or being stuck with (AND OR'ing all your options).
Since you have a list of values of what you want to retain, dump that into a temporary table. Then do a delete against the base table for what does not exist in the temporary table (left outer join). I suck at mysql syntax or I'd cobble together your query. Psuedocode is approximate
DELETE
B
FROM
BASE B
LEFT OUTER JOIN
#RETAIN R
ON R.key1 = B.key1
AND R.key2 = B.key
WHERE
R.key1 IS NULL
The NOT EXISTS version:
DELETE
b
FROM
BaseTable b
WHERE
NOT EXISTS
( SELECT
*
FROM
RetainTable r
WHERE
(r.key1, r.key2) = (b.key1, b.key2)
)