2017-06-07 1 views
0

Après la my question j'ai les tableaux ci-dessous la première (plage) comprend plage de valeurs et des colonnes supplémentaires:Réduction du nombre d'enregistrements à l'aide gamme rejoindre

row | From | To  | Country .... 
-----|--------|---------|--------- 
1 | 1200 | 1500 | 
2 | 2200 | 2700 | 
3 | 1700 | 1900 | 
4 | 2100 | 2150 | 
... 

Le From et To sont bigint et sont exclusifs . La table Range inclut 1,8 million d'enregistrements. table supplémentaire (valeurs) contient des enregistrements de 2,7 millions et ressemble à:

row  | Value | More columns.... 
--------|--------|---------------- 
    1 | 1777 |  
    2 | 2122 |  
    3 | 1832 |  
    4 | 1340 |  
    ... 

Je voudrais créer une table comme suit:

row  | Value | From | To | More columns.... 
--------|--------|--------|-------|--- 
    1 | 1777 | 1700 | 1900 | 
    2 | 2122 | 2100 | 2150 | 
    3 | 1832 | 1700 | 1900 | 
    4 | 1340 | 1200 | 1500 | 
    ... 

J'ai utilisé la jointure externe gauche dans le code suivant:

set n=1000; 

select  v.id 
      ,v.val 
      ,r.from_val 
      ,r.to_val 

from  val v 
     left outer join  

(select r.* 
        ,floor(from_val/${hiveconf:n}) + pe.i as match_val 

      from val_range r 
        lateral view posexplode 
            (
             split 
             (
              space 
              (
               cast 
               (
                floor(to_val/${hiveconf:n}) 
                - floor(from_val/${hiveconf:n}) 

                as int 
               ) 
              ) 
              ,' ' 
             ) 
            ) pe as i,x 
      ) r 



      on  floor(v.val/${hiveconf:n}) = 
        r.match_val 

where  v.val between r.from_val and r.to_val 

order by v.id  
; 

Cependant, il y a une grande réduction du nombre d'enregistrements de la nouvelle table ~ 31k enregistrements sur 2,7M. Comment cela peut-il être si j'utilise le left outer join? Comment puis-je le réparer?

+0

Bonjour Avi :-) Il y a un filtrage sur 'r' ('v.val entre r.from_val et r.to_val') qui annule en fait la fonctionnalité de LEFT JOIN et le transforme en INNER JOIN et apparemment toutes les valeurs ne sont pas couvertes par des plages. –

+0

Merci beaucoup! Comment puis-je utiliser la fonctionnalité de Left Join? l'entre est essentiel car il détermine la gamme requise à la valeur pertinente? Je ne voudrais pas omettre des valeurs qui n'ont pas de portée. – Avi

+0

Je suppose que v.id est unique? –

Répondre

1

En supposant que nous avons un v.id

set n=1000; 

select  v.id 
      ,r.from_val 
      ,r.to_val 

from     val  v 

      left join (select  v.id 
            ,r.from_val 
            ,r.to_val 

         from    val  v 

            join (...) r 

            on  floor(v.val/${hiveconf:n}) = 
              r.match_val 

         where  v.val between r.from_val and r.to_val 
         ) r 

      on   r.id = 
         v.id 

order by v.id  

En ce qui concerne la demande OP, voici la requête complète:

set n=1000; 

select  v.id 
      ,r.from_val 
      ,r.to_val 

from     val  v 

      left join (select  v.id 
            ,r.from_val 
            ,r.to_val 

         from    val  v 

            join (select r.* 
                ,floor(from_val/${hiveconf:n}) + pe.i as match_val 

              from val_range r 
                lateral view posexplode 
                    (
                     split 
                     (
                      space 
                      (
                       cast 
                       (
                        floor(to_val/${hiveconf:n}) 
                        - floor(from_val/${hiveconf:n}) 

                        as int 
                       ) 
                      ) 
                      ,' ' 
                     ) 
                    ) pe as i,x 
              ) r 

            on  floor(v.val/${hiveconf:n}) = 
              r.match_val 

         where  v.val between r.from_val and r.to_val 
         ) r 

      on   r.id = 
         v.id 

order by v.id  
+0

Cher @Dudu Markovitz, pourriez-vous s'il vous plaît remplir la jointure (...). Je pense qu'il y a deux fois l'alias pour r. En outre, pouvez-vous expliquer pourquoi vous avez ajouté r.id = v.id? Puisque même j'ajoute le numéro de ligne comme identifiant unique pour chaque table, ils ne sont pas censés être égaux? Merci beaucoup. – Avi

+1

Ajouté Il n'y a aucun problème avec la réutilisation des alias dans différentes portées. 'r.id' est en fait' v.id' dans une sous-requête aliasée par 'r' –