Ontdubbelen (MySQL)

Uit De Vliegende Brigade
Ga naar: navigatie, zoeken

Er lijkt een categorie te bestaan van 'leipe MySQL-problemen'. Zoiets als wat discrete wiskunde is voor wiskunde-in-het-algemeen. Ontdubbelen lijkt in deze categorie te vallen, net als het matchen van ongerelateerde tabellen.

Sleutel + ignore

Een eenvoudige truuk om dubbelen weg te toveren: Defineer een nieuwe tabel, en maak van de kolom die ontdubbelt moet worden, de primaire sleutel. Gebruik bij invoegen in deze tabel het keyword ignore. Zoiets als insert ignore into.

Distinct

[1]:

The go to solution for removing duplicate rows from your result sets is to include the distinct keyword in your select statement. It tells the query engine to remove duplicates to produce a result set in which every row is unique. Did you know that the group by clause can also be used to remove duplicates? If not, read on to find out what the main differences are between them and which to use to produce a desired result.

Het keyword distinct zorgt ervoor, dat alleen unieke rijen getoond worden. Dit heeft niet met PK's te maken en het heeft ook niet alleen betrekking op het veld dat direct na distinct komt - Zo lang er maar ergens een verschil is. Voorbeeld:

drop table if exists tmp;
    
create table
   tmp
   (
      first_name   varchar(40),
      last_name    varchar(40),
      age          smallint
   );

insert into
   tmp
values
   ("Jan",   "Jansen",    28), # 1
   ("Piet",  "Pietersen", 30), # 2
   ("Jan",   "Jansen",    28), # 3
   ("Jan",   "Jansen",    32), # 4
   ("Klaas", "Jansen",   100); # 5


# Returns all 5 records
########################################
#
select * from tmp;


# Returns 4 records
########################################
#
# There is only one duplicate: row 1 = row 3
# 
select distinct * from tmp;


# Returns 3 records
########################################
#
# Here, only the first name is returned. In this case, there
# are only 3 distinct rows
#
select distinct first_name from tmp;

Group by

group by lijkt op distinct. Vaak doen ze hetzelfde, behalve als het om geaggregeerde functies. Toch zijn er meer verschillen:

  • distinct is als een filter, dat op het laatste moment zorgt dat alleen unieke data wordt getoond - Het filtert en vermindert de data
  • group by maakt dingen expliciet; het forceert dat unieke data expliciet getoond wordt - relevant, in combinatie met aggregated functions (zie verderop); het expandeert de data
  • group by heeft nog een voordeel: De velden die uniek moeten zijn, zijn niet automatisch alle velden die getoond worden - Zie voorbeelden hieronder.

Om simpel te beginnen: Het resultaat dat hierboven werd bereikt middels distinct kun je ook bereiken met behulp van group by:

select * from tmp group by first_name, last_name

Het handige aan group by is, dat je specifieker kunt zijn, welke velden uniek moeten zijn. Het is daarom al snel onmisbaar in combinatie met aggregated functions', omdat die van nature records samenvoegt. Je kunt dan group by gebruiken om aan te geven welke velden unieke waardes moeten behouden.

Voorbeeld, gebaseerd op de eerdergenoemde voorbeelddata:

# Return 4 unique records
########################################
#
# Same as when using 'distinct'
#
select
   *
from
   tmp
group by
   first_name,
   last_name,
   age;


# Return 3 unique records
########################################
#
# * Only "first_name" has to be unique, hence 3 records are returned
# * Difference with 'distinct': You can show more columns, but filter only on 
#   some
#
select
   *
from
   tmp
group by
   first_name;

Aggregate functions

Het hoort misschien niet helemaal in dit hoofdstuk thuis, maar handig om nu gelijk aggregate functions te bespreken.

Samenvoegen

Aggregate functies voegen informatie samen, uit meerdere bronnen, in dit geval rijen. Ze verminderen dus data.

Waarschijnlijk het bekendste voorbeeld van een aggregated function, is om het aantal records in een verzameling te tellen. Bv.:

select count(*) from tmp

5

Voorbeeld: De code

select
   first_name,
   last_name,
   sum(age)
from
   tmp;

geeft als resultaat:

Jan Jansen 218

Door de aggregate function sum() worden records geaggregeerd. Daarom houd je maar één record over. Het getal 218 is de som van de leeftijden van alle records. Jan Jansen wordt vermoedelijk getoond, omdat dat uit de eerste rij komt - Meestal niet bijster relevant.

Aggregate & distinct

Dit voorbeeld van een aggregate function icm. distinct, levert niets spannends op:

select distinct
   first_name,
   last_name,
   sum(age)
from
   tmp;

Jan Jansen 218

Aggregate & group by

Hier zie je wat group by echt doet: Het maakt dingen expliciet - Het forceert dat alle unieke waardes van het gegeven veld (of velden) expliciet getoond worden:

select
   first_name,
   last_name,
   sum(age)
from
   tmp
group by
   first_name; 


Jan     Jansen      88
Piet    Pietersen   30
Klaas   Jansen      100

Wat er nu gebeurt: De records voor first_name = Jan worden geaggregeerd. De leeftijd 88 is de som van de leeftijden van alle drie de records met de voornaam Jan

Zie ook

Bronnen