I have a table with duplicates (COL2) within the same category (defined in COL1), when I try to delete tuples within COL2, I can't find a way to do this only within the same category, instead it deletes tuples everywhere in the table.
Here is the current table T1 BEFORE removing duplicates:
COL1 COL2
A 1
A 2
A 2
A 2
B 1
B 2
B 2
B 3
Here is the current table T1 AFTER removing duplicates:
COL1 COL2
A 1
A 2
B 3
Here is what I should have in T1:
COL1 COL2
A 1
A 2
B 1
B 2
B 3
Here is the code I used to delete duplicates:
CREATE TABLE TEMP LIKE T1;
INSERT INTO TEMP SELECT * FROM T1 WHERE 1 GROUP BY COL2;
DROP TABLE T1;
ALTER TABLE TEMP RENAME T1;
Any idea how to tell mysql to delete tuples only within a category of COL1?
Use both columns in your GROUP BY clause:
INSERT INTO TEMP
SELECT *
FROM T1
GROUP BY COL1, COL2
Related
I was trying to create a new column in SQL which has calculated values from other columns in the same table.
Please see the case below
col1 col2
A 1
A 2
B 1
B 2
B 3
I need to create a new column 'col3' that finds the max of col2 grouped by col1. So the result i want is
col1 col2 col3
A 1 2
A 2 2
B 1 3
B 2 3
B 3 3
I would like to know if a query can be something along the below lines
ALTER TABLE table1 ADD col3 AS (SELECT max(col2) GROUPBY col1)
You don't need an ALTER statement and can get the extra column in your SELECT query like
select col1, col2, max(col2) as col3
from tbl1
group by col1
I want to generate a new column in my table that is true if a row exists with certain conditions.
name | col1 | col2 | flag
--------------------------
a 1 2 0
a 2 3 0
b 1 2 0
b 4 3 0
Lets say I want to set the flag to 1 for every name identifier if a row exists with that name and where col1=2 and col2 = 3. So this would result in:
name | col1 | col2 | flag
--------------------------
a 1 2 1
a 2 3 1
b 1 2 0
b 4 3 0
because for a a row with col1=2 and col2 = 3 exists, but for b, such a row doesn't exist.
In pseudocode I want something like this:
ALTER TABLE table_name
ADD flag TINYINT(1)
IF ##row with condition col1=value1 and col2=value2 exists#
GROUP BY name
How can I generate this column?
So you want just to get those values from db? or you want to add column? those are 2 different goals.
So if you need just to get those values you can:
http://sqlfiddle.com/#!9/65b4c2/1
SELECT t.*, t2.flag
FROM table_name t
LEFT JOIN (
SELECT name, MAX(IF(col1=2 AND col2=3,1,0)) flag
FROM table_name
GROUP BY name
) t2
ON t.name = t2.name
and if you really need to add new column then you go this way:
http://sqlfiddle.com/#!9/226fb3/1
ALTER TABLE table_name ADD COLUMN flag TINYINT;
UPDATE table_name t
LEFT JOIN (
SELECT name, MAX(IF(col1=2 AND col2=3,1,0)) flag
FROM table_name
GROUP BY name
) t2
ON t.name = t2.name
SET t.flag=t2.flag
I have one log table and one view.
I would like to fetch the changed rows from the view by comparing it to the log table given an ID_NO.
The ID_NO is fixed between the two tables, whereas other columns can change.
In short, I would like to fetch the rows from Table1 which have one more changed columns in comparison to Table2.
for example:
TABLE 1:
ID COL1 COL2 COL3
1 A B C
2 34 56 D
3 F XY 24
TABLE 2:
ID COL1 COL2 COL3
1 A B C
2 34 56 F
3 1 XY 24
The query should return the following from TABLE2:
ID COL1 COL2 COL3
2 34 56 F
3 1 XY 24
Please advise.
Many Thanks!
SELECT *
FROM one_view vw
WHERE EXISTS
(
SELECT 1
FROM log_table t
WHERE vw.id_no = t.id_no
)
;
A note after the question was updated:
SELECT *
FROM table_2 t1
WHERE EXISTS
(
SELECT 1
FROM table_1 t2
WHERE t1.id_no = t2.id_no
AND
(
t1.col1 <> t2.col1
OR t1.col2 <> t2.col2
OR t1.col3 <> t2.col3
)
)
;
you could add a trigger to the changing table that inserts the id in a second table that is used to identify the changed rows from the changing table. Just comparing the values between tables might work but requires a lot of work. Getting the id's of the changed rows might be easier.
Just in case you also want to have the old values, add the changed colums and values to the logging table.
I feel weird, as every other answer says it works, but I can't get the correct results :(
table A: id_num, name<br>
table B: id_num
table A has index on name, but not unique. id_num is unique in this table.<br>
table B has index on id_num, but not unique.
I want to get table A names, who are NOT in table B.
This not working:
**SELECT a.name FROM a
LEFT JOIN b ON (a.id_num = b.id_num)
WHERE b.id_numb IS NULL**
its returning names that ARE in table b (and some that are not).
this didn't work either:
**SELECT distinct(a.name)
FROM a where a.id_num
not in (select distinct(b.id_num) from b )**
I can't comprehend how a.names are being return who ARE IN table B, when the SQL says NOT IN.
what am I missing?
thanks
By right, the left join should work. And as well as in.
Here is a sample. So you may want to publish and show your table schema and data for more justice on your question. Best if you could just create the tables on SQLFIDDLE and show the reference. ;)
Here is just SAMPLE:-
SQLFIDDLE reference
Sample Tables:
tab1:
COL1 COL2
1 john
2 tim
3 jack
4 rose
tab2:
COL3 COL4
1 2
2 3
3 5
4 5
5 2
Query:
select * from tab1
where col1 not in
(select distinct col4 from tab2)
;
Results:
COL1 COL2
1 john
4 rose
As per OP's updated comments and table structure
OP mentioned the table tab1 will have multiple records for same name. According to his original table design, there's NO NAME field in the table tab2. It's also much recommended if OP had provided the expected results initially.
* SQLFIDDLE Reference
OP's table data:
COL1 COL2
1 john
2 tim
3 jack
4 rose
5 john
6 john
COL3 COL4
1 2
2 3
3 5
4 5
5 2
6 6
Query: When you do not want any name that is duplicated
select t.col1, t.col2
from tab1 t
join
(select t1.col2, count(*) as counts
from tab1 t1
group by t1.col2
having count(*) = 1) x
on t.col2 = x.col2
where t.col1 not in
(select distinct col4 from tab2)
;
Results: Here is Rose, the only record that has no duplicates and do not exist in tab2
COL1 COL2
4 rose
try this
select t1.name from table1 t1
where t1.name not in
(select t2.name from table2 t2 )
look the DEMO SQLFIDDLE
EDIT:
if you have only id_num in your second table then here look to
THIS DEMO SQLFIDDLE
Suppose this table:
ID ColA ColB
1 7 8
2 7 9
3 7 9
4 5 8
5 6 9
6 6 9
7 5 4
The PK is the ID coumn.
Now, I want to delete all duplicates of ColA and ColB in consecutive rows.
In this example rows 2,3 and 5,6 contain duplicates.
These shall be removed so that the higher ID is remained.
The output should be:
ID ColA ColB
1 7 8
3 7 9
4 5 8
6 6 9
7 5 4
How can this be done with mySQL?
Thanks,
Juergen
SELECT
ID
FROM
MyTable m1
WHERE
0 < (SELECT
COUNT(*)
FROM
MyTable m2
WHERE
m2.ID = m1.ID - 1 AND
m2.ColA = m1.ColA AND
m2.ColB = m1.ColB)
and then you can use a
delete from MyTable where ID in ...
query. This way it would surely work in any version.
CREATE TEMPORARY TABLE duplicates (id int primary key)
INSERT INTO duplicates (id)
SELECT t1.id
FROM table t1
join table t2 on t2.id = t1.id + 1
WHERE t1.ColA = t2.ColA
and t1.ColB = t2.ColB
-- SELECT * FROM duplicates --> are you happy with that? => delete
DELETE table
FROM table
join duplicates on table.id = duplicates.id
Depending on how many records you have, this might not be the most efficient:
SELECT (SELECT TOP 1 id FROM table WHERE colA = m.colA AND colB = m.colB ORDER BY id DESC) AS id, m.*
FROM (SELECT DISTINCT colA, colB
FROM table) m
There might be syntax errors because I usually use mssql, but the idea should be similar.
I've called the first table 'test'.
Firstly create a table that will hold all the identical combinations of ColA and ColB:
create temporary table tmpTable (ColA int, ColB int);
insert into tmpTable select ColA,ColB from test group by ColA, ColB;
Now, select the maximum id in the original table for each identical combination of ColA and ColB. Put this into a new table (called idsToKeep because these are the rows we do not want to delete):
create temporary table idsToKeep (ID int);
insert into idsToKeep select (select max(ID) from test where test.ColA=tmpTable.ColA and test.ColB=tmpTable.ColB) from tmpTable;
Finally, delete all the entries from the original table that are not in the idsToKeep table:
delete from test where ID <> all (select ID from idsToKeep);