This question stumps me. I have a database with a table that has a primary key that consists of two fields. In the end I require that the primary key only be one field, but I need to delete the duplicate entries from the table.
In other words the table has:
PRIMARY KEY (`field1`, `field2`)
There are entries that have duplicate field1 and different field2. So I have entries like this:
field1 | field2
1 | 1
1 | 2
2 | 1
2 | 2
3 | 1
4 | 1
I want to delete 1 of each of those entries that have duplicates on field1.
How can I do this with MySQL / SQL?
I think this will work in your case,
DELETE t1 FROM table t1
INNER JOIN table t2
WHERE t1.id > t2.id
AND t1.field1 = t2.field1
In this query I am joining the same table and picking duplicate values of field1 with different id and removing those.
Hope this works!!
I dont know how the delete from table needs to be specified in the mysql syntax but essentially you are trying to remove the second entry for the field1 for each of its unique value. So in some way if you are able to retrieve those records and pass them as select statements under your delete from table clause it should work.
For instance, here is the query that would select 2nd row for each value of field1 if it is repeated
select field1, field2
from
(
select *, count(*) over (partition by field1) as ct
, rank() over (partition by field1 order by field2 desc) as rn
from temp
) where rn = 1 and ct = 2
In your case it would return below records
field1 field2
1 2
2 2
So then all you need to do is have a delete from table clause at the top of that select statement.
NOTE - I have tried a solution without a join and hence I maintain these 2 analytical functions.
For instance this works in something like BigQuery -
delete from TABLE where concat(field1, field2) in
(
select concat(field1, field2)
from
(
select *, count(*) over (partition by field1) as ct
, rank() over (partition by field1 order by field2 desc) as rn
from TABLE
) where rn = 1 and ct = 2
)
hi I have one table which I am trying to get the count of different rows on the same row field for example I a have this rows
Function field1 field2 field3
'dog' 1 1 5
'dog' 1 1 5
'cat' 1 1 5
'dog' 1 2 6
The output for this table should be:
Function count
'dog' 2
'cat' 1
because there are two different rows for 'dog' (some of the field are different) and one row for 'cat'
thank you so much
Assuming that you want to count rows identical based on a given subset of fields, this would be:
SELECT func, COUNT(*) FROM (
SELECT DISTINCT func, field1, field2 FROM yourtable
) AS tmp GROUP BY func;
This first distincts all the rows, so you get
'dog' 1 1 5
'cat' 1 1 5
'dog' 1 2 6
and then counts the first field, thus giving 2 and 1.
You can even do something like
SELECT func, COUNT(*) AS different, SUM(total) AS total FROM (
SELECT func, field1, field2, field3, COUNT(*) AS total
FROM yourtable
GROUP BY func, field1, field2, field3
) AS tmp GROUP BY func;
which will give:
func different total
dog 2 3
cat 1 1
This should give you the results you are looking for:
Select Function, Count(*) As Count
From
(
Select Distinct
Function,
Field1,
Field2,
Field3
From YourTable
) As A
Group By Function
SELECT DISTINCT field1, field2, field3, ......
FROM table;
I am trying to accomplish the following SQL statement, but I want it to return all columns.
Is this possible?
Something like this:
SELECT DISTINCT field1, *
FROM table;
You're looking for a group by:
select *
from table
group by field1
Which can occasionally be written with a distinct on statement:
select distinct on field1 *
from table
On most platforms, however, neither of the above will work because the behavior on the other columns is unspecified. (The first works in MySQL, if that's what you're using.)
You could fetch the distinct fields and stick to picking a single arbitrary row each time.
On some platforms (e.g. PostgreSQL, Oracle, T-SQL) this can be done directly using window functions:
select *
from (
select *,
row_number() over (partition by field1 order by field2) as row_number
from table
) as rows
where row_number = 1
On others (MySQL, SQLite), you'll need to write subqueries that will make you join the entire table with itself (example), so not recommended.
From the phrasing of your question, I understand that you want to select the distinct values for a given field and for each such value to have all the other column values in the same row listed. Most DBMSs will not allow this with neither DISTINCT nor GROUP BY, because the result is not determined.
Think of it like this: if your field1 occurs more than once, what value of field2 will be listed (given that you have the same value for field1 in two rows but two distinct values of field2 in those two rows).
You can however use aggregate functions (explicitely for every field that you want to be shown) and using a GROUP BY instead of DISTINCT:
SELECT field1, MAX(field2), COUNT(field3), SUM(field4), ....
FROM table GROUP BY field1
If I understood your problem correctly, it's similar to one I just had. You want to be able limit the usability of DISTINCT to a specified field, rather than applying it to all the data.
If you use GROUP BY without an aggregate function, which ever field you GROUP BY will be your DISTINCT filed.
If you make your query:
SELECT * from table GROUP BY field1;
It will show all your results based on a single instance of field1.
For example, if you have a table with name, address and city. A single person has multiple addresses recorded, but you just want a single address for the person, you can query as follows:
SELECT * FROM persons GROUP BY name;
The result will be that only one instance of that name will appear with its address, and the other one will be omitted from the resulting table. Caution: if your fileds have atomic values such as firstName, lastName you want to group by both.
SELECT * FROM persons GROUP BY lastName, firstName;
because if two people have the same last name and you only group by lastName, one of those persons will be omitted from the results. You need to keep those things into consideration. Hope this helps.
That's a really good question. I have read some useful answers here already, but probably I can add a more precise explanation.
Reducing the number of query results with a GROUP BY statement is easy as long as you don't query additional information. Let's assume you got the following table 'locations'.
--country-- --city--
France Lyon
Poland Krakow
France Paris
France Marseille
Italy Milano
Now the query
SELECT country FROM locations
GROUP BY country
will result in:
--country--
France
Poland
Italy
However, the following query
SELECT country, city FROM locations
GROUP BY country
...throws an error in MS SQL, because how could your computer know which of the three French cities "Lyon", "Paris" or "Marseille" you want to read in the field to the right of "France"?
In order to correct the second query, you must add this information. One way to do this is to use the functions MAX() or MIN(), selecting the biggest or smallest value among all candidates. MAX() and MIN() are not only applicable to numeric values, but also compare the alphabetical order of string values.
SELECT country, MAX(city) FROM locations
GROUP BY country
will result in:
--country-- --city--
France Paris
Poland Krakow
Italy Milano
or:
SELECT country, MIN(city) FROM locations
GROUP BY country
will result in:
--country-- --city--
France Lyon
Poland Krakow
Italy Milano
These functions are a good solution as long as you are fine with selecting your value from the either ends of the alphabetical (or numeric) order. But what if this is not the case? Let us assume that you need a value with a certain characteristic, e.g. starting with the letter 'M'. Now things get complicated.
The only solution I could find so far is to put your whole query into a subquery, and to construct the additional column outside of it by hands:
SELECT
countrylist.*,
(SELECT TOP 1 city
FROM locations
WHERE
country = countrylist.country
AND city like 'M%'
)
FROM
(SELECT country FROM locations
GROUP BY country) countrylist
will result in:
--country-- --city--
France Marseille
Poland NULL
Italy Milano
SELECT c2.field1 ,
field2
FROM (SELECT DISTINCT
field1
FROM dbo.TABLE AS C
) AS c1
JOIN dbo.TABLE AS c2 ON c1.field1 = c2.field1
Great question #aryaxt -- you can tell it was a great question because you asked it 5 years ago and I stumbled upon it today trying to find the answer!
I just tried to edit the accepted answer to include this, but in case my edit does not make it in:
If your table was not that large, and assuming your primary key was an auto-incrementing integer you could do something like this:
SELECT
table.*
FROM table
--be able to take out dupes later
LEFT JOIN (
SELECT field, MAX(id) as id
FROM table
GROUP BY field
) as noDupes on noDupes.id = table.id
WHERE
//this will result in only the last instance being seen
noDupes.id is not NULL
Try
SELECT table.* FROM table
WHERE otherField = 'otherValue'
GROUP BY table.fieldWantedToBeDistinct
limit x
You can do it with a WITH clause.
For example:
WITH c AS (SELECT DISTINCT a, b, c FROM tableName)
SELECT * FROM tableName r, c WHERE c.rowid=r.rowid AND c.a=r.a AND c.b=r.b AND c.c=r.c
This also allows you to select only the rows selected in the WITH clauses query.
For SQL Server you can use the dense_rank and additional windowing functions to get all rows AND columns with duplicated values on specified columns. Here is an example...
with t as (
select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r1' union all
select col1 = 'c', col2 = 'b', col3 = 'a', other = 'r2' union all
select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r3' union all
select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r4' union all
select col1 = 'c', col2 = 'b', col3 = 'a', other = 'r5' union all
select col1 = 'a', col2 = 'a', col3 = 'a', other = 'r6'
), tdr as (
select
*,
total_dr_rows = count(*) over(partition by dr)
from (
select
*,
dr = dense_rank() over(order by col1, col2, col3),
dr_rn = row_number() over(partition by col1, col2, col3 order by other)
from
t
) x
)
select * from tdr where total_dr_rows > 1
This is taking a row count for each distinct combination of col1, col2, and col3.
select min(table.id), table.column1
from table
group by table.column1
SELECT *
FROM tblname
GROUP BY duplicate_values
ORDER BY ex.VISITED_ON DESC
LIMIT 0 , 30
in ORDER BY i have just put example here, you can also add ID field in this
Found this elsewhere here but this is a simple solution that works:
WITH cte AS /* Declaring a new table named 'cte' to be a clone of your table */
(SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY val1 DESC) AS rn
FROM MyTable /* Selecting only unique values based on the "id" field */
)
SELECT * /* Here you can specify several columns to retrieve */
FROM cte
WHERE rn = 1
In this way can get 2 unique column with 1 query only
select Distinct col1,col2 from '{path}' group by col1,col2
you can increase your columns if need
Add GROUP BY to field you want to check for duplicates
your query may look like
SELECT field1, field2, field3, ...... FROM table GROUP BY field1
field1 will be checked to exclude duplicate records
or you may query like
SELECT * FROM table GROUP BY field1
duplicate records of field1 are excluded from SELECT
Just include all of your fields in the GROUP BY clause.
It can be done by inner query
$query = "SELECT *
FROM (SELECT field
FROM table
ORDER BY id DESC) as rows
GROUP BY field";
SELECT * from table where field in (SELECT distinct field from table)
SELECT DISTINCT FIELD1, FIELD2, FIELD3 FROM TABLE1 works if the values of all three columns are unique in the table.
If, for example, you have multiple identical values for first name, but the last name and other information in the selected columns is different, the record will be included in the result set.
I would suggest using
SELECT * from table where field1 in
(
select distinct field1 from table
)
this way if you have the same value in field1 across multiple rows, all the records will be returned.
I have a query like this and using infobright database --
select field1, field2
from foo
where filed1 in (1,2,3)
I want something to return even if there is no record in table. For example, there is record for filed1 = 2
and filed1 = 2 but nothing exists for filed1 = 3.
How could I make this query so I get something returning from the table for field1 = 3 ?
I could use ifnull in case there is a null value in the table for field1 = 3, but what I am trying find if there is absolutely nothing exists.
Although this is a short list of ID values you want, you can create a select/union to create the IDs, then left-join to the data table something like
select
AllIDs.ID,
foo.field1,
foo.field2
from
( select 1 ID union select 2 union select 3 ) as AllIDs
left join foo
on AllIDs.ID = foo.field1
If field1 is unique you can do this:
SELECT
ISNULL(MAX(field1), 'Default F1') as field1,
ISNULL(MAX(field2), 'Default F2') as field2
FROM foo
WHERE field1 in (1,2,3)
GROUP by field1
Otherwise you can use UNION like this:
SELECT field1, field2
FROM foo
WHERE filed1 in (1,2,3)
UNION
SELECT 'Default F1' as field1, 'Default F2' as field2
WHERE (SELECT COUNT(*) FROM foo WHERE filed1 in (1,2,3)) = 0
I have a mysql table that has two fields that store the same type of information. I want to retrieve all unique values in those two fields.
If it were just one field I could do:
SELECT distinct FIELD1 FROM table
How can I get all unique values from FIELD1 and FIELD2
Clarification:
I don't mean unique pairs.
Say field1 contains 1,13,5,25,13,8
and field2 contains 6,10,1,30,13
I want a query that returns 1,13,5,25,8,6,10,30
Try this
select distinct * FROM (
select distinct field1 as n from table
union
select distinct field2 as n from table) as t;
select field1 ,field2 FROM tablename group by field1 ,field2
select field1 from table
union
select field2 from table
You mean all unique pairs? Then this might do (a bit dirty, though):
SELECT distinct CONCAT(FIELD1, '|', FIELD2) FROM table
You can do a union of two sql statements:
Select distinct FIELD1 From table
UNION
Select distinct FIELD2 From table