2
votes

Sélectionnez les lignes dans SQL avec les données de colonne les plus denses (le moins NULL)

J'ai plusieurs identifiants en double, qui doivent être réduits à une seule valeur. Normalement, j'utiliserais une méthode d'agrégation pour combiner les valeurs de colonne (sous forme de somme, de moyenne, etc.). Ici, je souhaite simplement conserver la ligne avec le plus grand nombre de valeurs non nulles dans toutes les colonnes:

étant donné ce tableau:

id   col1   col2   col3
2    x      y      ''
1    a      b      c

Comment je pourrais sélectionner :

id   col1   col2   col3
1    a      ''     ''
1    a      b      ''
2    x      y      ''
1    a      b      c
2    s      ''     ''

sql

3 commentaires

Quels rdbms utilisez-vous et ce tableau contient-il uniquement ces 4 colonnes?


Une combinaison de colonnes peut-elle être nulle, ou est-ce uniquement [null, null, null], [a, null, null] ou [a, b, null]. aussi, voulez-vous vraiment dire NULL, votre exemple a des valeurs de «» dans ces colonnes


Quel SGBD utilisez-vous? "SQL" n'est qu'un langage de requête, pas le nom d'un produit de base de données spécifique. Veuillez ajouter la balise du produit de base de données que vous utilisez postgresql , oracle , db2 , sql-server ,. ..


3 Réponses :


0
votes

Vous pouvez utiliser une requête pour la somme maximale non nulle et joindre par exemple, limiter aux 2 premiers

select m.* from  
my_table m
INNER JOIN (
  select id
   , if (col1 is null, 0, 1)  + 
     if (col2 is null, 0,  1)  + 
     if (col3 is null, 0, 1)   result 

  from my_table 
  order by  result desc 
  limit 2
) t on t.id = m.id 


1 commentaires

Cette réponse est un peu ridicule. Cela peut fonctionner pour les données particulières des OP, mais cela ne ferait pas la chose attendue s'il y avait plus de deux identifiants ou si les identifiants étaient liés pour le nombre de colonnes non NULL.



2
votes

Avec cette requête:

select t.* from tablename t
inner join (
  select id, 
    max(
      (case when col1 is not null then 1 else 0 end) +   
      (case when col2 is not null then 1 else 0 end) + 
      (case when col3 is not null then 1 else 0 end)
    ) maxnotnulls
  from tablename
  group by id
) g 
on 
  g.id = t.id
  and 
  (case when t.col1 is not null then 1 else 0 end) +   
  (case when t.col2 is not null then 1 else 0 end) + 
  (case when t.col3 is not null then 1 else 0 end) = g.maxnotnulls

vous pouvez obtenir pour chaque identifiant le nombre maximum de colonnes non nulles pour chaque identifiant.
Vous pouvez donc rejoindre la table avec la requête ci-dessus comme ceci:

select id, 
  max(
    (case when col1 is not null then 1 else 0 end) +   
    (case when col2 is not null then 1 else 0 end) + 
    (case when col3 is not null then 1 else 0 end)
  ) maxnotnulls
from tablename
group by id


0 commentaires

1
votes

En supposant que la chaîne vide est vraiment NULL , la méthode la plus simple en SQL standard est:

select t.*
from (select t.*,
             row_number() over (partition by id
                                order by ((case when col1 is not null then 1 else 0 end) +
                                          (case when col2 is not null then 1 else 0 end) +
                                          (case when col3 is not null then 1 else 0 end) desc
                                         )
                               ) as seqnum
      from t
     ) t
where seqnum = 1;

Bien sûr, cela s'adapte facilement aux comparaisons avec des chaînes vides.

/ p>


0 commentaires