How to select distinct value from one column only - mysql

I have records as follows:
key | name
--------------
1111 | aa
1111 | bb
2222 | cc
I need to select the key and name when the key value is distinct. When I tried:
select distinct key, name from table;
I got all the rows since the query takes distinct for the combination of the columns: key and name. But, what I need is only distinct key and I don't care about the name. I have a lot of records, so I need a practical method.

Query:
SELECT `key`, MAX(`name`) as name
FROM `table`
GROUP BY `key`

Why not just:
SELECT distinct key
FROM table
or
SELECT key, name
FROM table
GROUP BY key

SELECT key, name FROM table GROUP BY key;
This returns one row for each distinct value of key, and the value of name is arbitrarily chosen from the rows in that group. In practice, MySQL tends to return the value of name from the row physically stored first in the group, but that's not guaranteed.
As other answers show, you can put name into an aggregate expression.

How about this:
select * from table group by key having count(key) = 1

If you do not care about not groupped fields try this query -
select key, name from table group by key order by name
MySQL lets selecting fields without using aggregate function.
order by name helps to select first name from the group.

Related

Why am I getting "Duplicate entry" error on SELECT DISTINCT query?

I have the following query to append data into a table if it is unique:
INSERT INTO belgarath.players(tour_id, player_id, player_name_oc)
SELECT DISTINCT 0, ID_P, NAME_P FROM oncourt.players_atp
LEFT JOIN belgarath.players
ON belgarath.players.tour_id = 0
AND belgarath.players.player_id=oncourt.players_atp.ID_P;
I run this once on an empty table and it's fine. I delete a row and run it expecting MySQL to append the one deleted row. However, I get the following error code: Error Code: 1062. Duplicate entry '0-43042' for key 'players.unique_plyrs' . I have a unique key across tour_id and player_id and clearly it's failing because I'm trying to append a duplicate record.
Why would I be getting this if I'm only selecting distinct records to insert? How do I avoid getting this in future?
This should resolve your issue. Put a Where clause to check for belgarath.players.player_id is NULL.
INSERT INTO belgarath.players(tour_id, player_id, player_name_oc)
SELECT DISTINCT 0, ID_P, NAME_P FROM oncourt.players_atp
LEFT JOIN belgarath.players
ON belgarath.players.tour_id = 0
AND belgarath.players.player_id=oncourt.players_atp.ID_P
WHERE belgarath.players.player_id is NULL;
Hope this hint realted to Distinct keyword helps you. When we use distinct key it usually select distinct rows. So we can't expect it should return distinct values for only one column before which we have wrote distinct. Below example will better explain you what i am trying to say.
create table test(id1 int, id2 int);
insert into test values(1,1),(1,2),(1,3);
Here i have created a test table and when i use distinct keyword as used in below query
select distinct id1, id2 from test;
Then we'll get output like this:
id1 id2
1 1
1 2
1 3
You are inserting tour_ID as 0, and as you have defined tour_id and player_id as unique key in oncourt.players_atp table. So your select query is selecting tour_id as '0' every time. Because select query with distinct is getting really distinct records like say player_id is 1,2,3 and names are john, steve, bill respectively then select query will return this 3 records like (0, 1, john), (0, 2, steve), (0, 3, bill) and so on.
If your oncourt.players_atp table also has unique constraint and that table also contains tour_id then you can just copy tour ID from there. If tour_id is not present there and you want to generate it inside belgarath.players table only then in you table definition you can define tour id as a auto increment then it will generate unique id's there and then you don't need to select tour_id in your query you just have to insert player_id and player_name once you define tour_id as an autoincrement ID.
Hope this may help you.

How to make unique combination of columns values?

I have a table with data like this:
id | link | name | date
1 aa bob 1
1 aa tom 2
1 bb tom 3
2 cc lora 4
It means I can have not unique values in any column but I CAN'T have the same row with identical id link name (date doesn't matter). This is the example what I can't have:
id | link | name | date
1 aa bob 1
1 aa bob 2
I tried to:
ALTER TABLE table ADD UNIQUE KEY `uk_id_link_name` (id, link, name);
also:
ALTER TABLE `table` ADD UNIQUE `unique_index`(`id`, `link`, `name`);
But it gives me an error:
Duplicate entry
How to make unique rows (combination of columns values which is not unique)?
EDIT: I don't want to delete duplicates from table.
Your table already violates the unique constraint. So you need to get rid of the offending values.
You can delete all but the earliest date:
delete t
from t join
(select id, link, name, min(date) as mindate
from t
group by id, link, name
) tt
using (id, link, name)
where date > mindate;
When the data is compatible, you can add the unique constraint.
Note: back up/make a copy of the table before doing this, so you don't lose data that you might really need.
The correct syntax for SQL Server should be the next:
ALTER TABLE TableName ADD CONSTRAINT ConstraintName UNIQUE (id, link, name)
But before create the constraint, of course you should ensure that there are not existing rows braking the constraint, for example using this query:
SELECT id, link, name, COUNT(*)
FROM TableName
GROUP BY id, link, name
HAVING COUNT(*) >= 2
This query returns the duplicates grouping by the three fields: id, link, name
If the query returns rows, you have to solve these duplicates before create the unique constraint.

Select MySQL records that conflict with a proposed unique index

I have a set of records that I want to add a unique index to, however some existing records conflict with that index, so I want to identify them and remove them in order that the constraint can be placed on the data.
Is there a way I can write a SELECT query based around any record that contradicts the unique index?
Example:
Table has columns
id | user | question_id | response | is_current
I want a unique index such that
user | question_id | response |is_current
is not duplicated.
Is it possible to SELECT all records where that set of values is not unique?
Show non-unique:
select user,question_id,response,is_current,count(*) as theCount
from tablename
group by user,question_id,response,is_current
having theCount>1

Make a unique select statement in MySQL

I have a select statement which, at least should, return only unique userId. If this does not happen and userIds are double a user did input something illegal.
To illustrate we use a simple SELECT userId, name, FROM USER. Now, usually you will make the userId unique/primarykey at the table level. Just for the sake of the example we don't.
The expected result would be:
userId name
---------------
1 Roel
2 Joe
3 John
But the result is something like
userId name
---------------
1 Roel
1 Roel
2 Joe
3 John
3 John
Is there possiblity to make the query in such a way that it would give an error when the result contains more than one the userIds?
Just add DISTINCT. And it will make your rows unique.
SELECT DISTINCT userId, name
FROM USER
By definition, the DISTINCT keyword can be used to return only distinct (different) values.
UPDATE 1
The reason why is that you didn't specify a constraint on your table. Make a table definition like this.
CREATE TABLE userList
(
ID INT NOT NULL AUTO_INCREMENT,
NAME VARCHAR(50) NOT NULL,
CONSTRAINT id_PK PRIMARY (ID),
CONSTRAINT name_unique UNIQUE (NAME)
)
when you don't want ID to be auto_incremented, you can remove the AUTO_INCREMENT word on the table definition, or create a table definition like this
CREATE TABLE userList
(
ID INT NOT NULL,
NAME VARCHAR(50) NOT NULL,
CONSTRAINT id_PK PRIMARY (ID),
CONSTRAINT name_unique UNIQUE (ID, NAME)
)
SELECT
UserId, COUNT(*)
FROM
User
GROUP BY
UserId
HAVING
COUNT(*) > 1
Any records returned from this will be those for which there is erroneous data. That would be the simplest way to identify when to raise an error, but it wouldn't simply raise one for you. You could wrap the above query into a procedure, and use some logic to determine whether to raise an error or run the main query.
Well, I guess this is importent during registration... so just count() the hits of a given username before you allow an INSERT.
Secondly make the name column UNIQUE and then you get the right error upon INSERT
Another solution is
SELECT *
FROM User
UNION
SELECT *
FROM User
The advantage of this is that you don't have to list the variables in SELECT. Usually, it is bad not to write explicitly the column names but I think this case is one of the rare cases where it makes sense.

Inserting into table in order

How can I insert values into a table (MySQL) in the following manner:
On all the rows of a table, in order of ID column (PK), insert incrementing number in column 'num'?
For example if the table had 3 rows , with Ids 1,5,2, I want ID 1 to get num=1, ID 2 to get num=2 and ID 5 to get num=3.
EDIT
I will explain why I (think I) need this:
I am trying to split a column off a table into a separate table with a 1-to-1 relation. I thought I would get all the values in order of ID and insert them into the new table, with an auto-incrementing PK. then I know that, in order of ID, the values for the new reference column in the original table will be auto-incrementing numbers. So I want to insert them in that order. I hope this is clear.
i am currently not in front of sql database engine and cannot therefore submit fully verified sql code. however if your num field is not an autoincrement field than do something like this:
CREATE TEMPORARY TABLE temp_table_x (
num int auto_increment primary key,
reference_id int
);
INSERT temp_table_x (reference_id)
SELECT id FROM source_table ORDER BY id;
UPDATE source_table st
SET st.num = x.num
FROM temp_table_x x
WHERE reference_id = id;
As long as the num field is an autoincrement field it should be as simple as:
INSERT INTO
yourTable (
field1,
field2,
field3,
etc
)
SELECT
field1,
field2,
field3
FROM
yourSourceTable
ORDER BY
originalIdField
I would NOT make a field that references a column in another table an auto-increment column.
Even if the column that it references is an auto-increment, I wouldn't make the column auto-increment. It will be difficult to keep the columns in sync. If an insert is rolled back in one table but not the other, you'll be out of sync until you reset the auto_increment value.
If it's a 1 to 1 relationship, feel free to make the column a primary key. That way it will be ordered by the column, and it will ensure unique values. However, if any two columns must match, they should not both be auto-increment, though, they should be of the same type (eg. INTEGER).
For example, here's our original table, where the first column is an auto-increment integer column:
id customer_name email_address
---------------------------
1 jsmith jsmith#aol.com
2 bwilliams bwilliams#aol.com
If you wanted to split the email_address off to its own table, in a 1 to 1 relationship:
id email_address
---------------------------
1 jsmith#aol.com
2 bwilliams#aol.com
I would make the first column an integer field and make it the primary key, but it would NOT be an auto-increment column.
To insert values into such a table, you could simply do this:
INSERT INTO table2
(id, email_address)
SELECT id, email_address
FROM table1
ORDER BY id
I found the answer. It is very simple:
SET #c=0;
UPDATE myTable SET num = (#c:=#c+1) ORDER BY id