3
votes

SQL pour ignorer la ligne maximale à condition

Je dois renvoyer la dernière ligne disponible, mais sous certaines conditions. Étant donné que Hive ne prend pas en charge PL-T / SQL, je dois travailler sur des fonctions.

Le code actuel sélectionne uniquement le dernier enregistrement et ne prend pas en compte ACTIVE_F .

MYUSER_INSERT_TIME        ACTIVE_F
2019-03-06 15:54:22.000   0

Mes données:

MYUSER_INSERT_TIME        ACTIVE_F
2019-06-14 15:00:32.000   6
2019-03-06 15:54:22.000   0
2019-01-25 08:43:45.000   1
2018-12-13 09:49:50.000   0
2018-11-24 10:11:06.000   0
2018-11-06 12:17:34.000   1
2018-07-04 16:59:15.000   0
2018-05-29 12:22:15.000   1
2018-05-24 20:19:00.000   2
2018-05-24 20:19:00.000   2

Comportement attendu:

  1. Rechercher le dernier enregistrement (terminé)

  2. Cochez ACTIVE_F (lorsque 6 - passez à la ligne suivante et renvoyez cette ligne, sinon passez à la ligne suivante)

Résultat souhaité:

WITH CTE AS 

(select 
ID, 
myuser_insert_time as insert_time,
max(myuser_insert_time) OVER (PARTITION BY ID ORDER BY ID) as rn
from tbl1)

SELECT * FROM CTE 
WHERE rn =  insert_time


4 commentaires

... de tbl1 où ACTIVE_F <> 6 ?


avez-vous une colonne dans la table à utiliser dans la clause order by ?


@Serg - Je ne peux pas simplement éliminer 6 car cela pourrait être le seul enregistrement dans certains cas.


@Shu - oui, MYUSER_INSERT_TIME


3 Réponses :


1
votes

Vous semblez simplement vouloir filtrer active_f = 6 , si je comprends bien. Vous devez le faire avant de calculer le temps maximum d'insertion; c'est-à-dire que dans le CTE:

with cte as (
      select ID, myuser_insert_time as insert_time,
             row_number() over (partition by id
                                order by (case when active_f = 6 then 2 else 1 end),
                                         myuser_insert_time desc
                               ) as rn
      from tbl1
    )
select * 
from CTE 
where rn = 1;

Votre max () avait également une colonne order by , vous preniez donc un max () . Ce n'est pas nécessaire. L'ordre par n'est pas nécessaire (même si le code a fonctionné).

EDIT:

Si vous avez besoin de "6" si c'est la seule ligne, alors utilisez row_number () et faites-en la dernière ligne:

with cte as (
      select ID, myuser_insert_time as insert_time,
             max(myuser_insert_time) over (partition by ID) as max_myuser_insert_time
      from tbl1
      where active_f <> 6
    )
select * 
from CTE 
where myuser_insert_time = insert_time;


5 commentaires

Malheureusement, éliminer 6 n'est pas une solution de contournement ici. Il peut y avoir un cas où une seule ligne existe - qui a 6 . S'il est le seul, il devrait être affiché.


@ marcin2x4. . . Je ne pense pas que ce soit clair dans la question.


Je vais réitérer. Je dois trouver la première dernière ligne qui apparaît après la ligne avec ACTIVE_F = 6 . Si la deuxième ligne est également 6 - continuez la boucle.


@ marcin2x4. . . C'est ce que fait le code édité.


order by (case when active_f = 6 then 2 else 1 end), myuser_insert_time DESC - DESC corrige le problème car j'ai besoin du dernier enregistrement (insérer l'heure) :)



1
votes

Ajoutez case when active_f = 6 puis 1 else 0 end à la clause order by de la fonction analytique. Les enregistrements avec active_f! = 6 seront préférés. Utilisez également row_number et order by myuser_insert_time desc:

WITH CTE AS 

(select 
ID, 
myuser_insert_time as insert_time,
row_number() OVER (PARTITION BY ID ORDER BY myuser_insert_time desc, case when active_f =6 then 1 else 0 end) as rn
from tbl1)

SELECT * FROM CTE 

WHERE rn =  1


1 commentaires

Presque là. J'ai besoin de la deuxième dernière ligne.



2
votes

Trier les lignes de manière conditionnelle par ACTIVE_F afin que les 6 prennent la suite de toutes les autres valeurs

WITH CTE AS 

(select 
ID, 
myuser_insert_time as insert_time,
row_number() OVER (PARTITION BY ID ORDER BY case ACTIVE_F when 6 then 1 else 0 end,  eendmyuser_insert_time desc) as rn
from tbl1)

SELECT * FROM CTE 
WHERE rn = 1


2 commentaires

Je pense que nous l'avons! Je vais tester sur des exemples de résultats et vous le faire savoir!


Cela fonctionne parfaitement! J'ai étendu CASE dans ORDER BY pour accueillir un indicateur supplémentaire qui doit être itéré à la deuxième place. ORDER BY case ACTIVE_F quand 6 puis 1 quand 0 puis 1 autre 0 fin, eendmyuser_insert_time desc