2014-10-02 10 views
6

Devo interrogare da un oracle 11 db. Con la query qui sotto ottengo tutti i recenti TAG_VALUE, TAG_DESC, INSERTION_DATE and PROJECT_ID dal mio database.Interrogare solo valori numerici il più presto possibile

SELECT * 
FROM (SELECT t.tag_value, 
       t.tag_desc, 
       u.update_as_of     AS INSERTION_DATE, 
       p.proj_id       AS PROJECT_ID, 
       Row_number() 
       over( 
        PARTITION BY p.proj_id 
        ORDER BY u.update_as_of DESC) RN 
     FROM project p 
       join update u 
       ON p.project_id = u.project_id 
       join tag t 
       ON t.tag_id = u.tag_id 
     WHERE t.tag_desc LIKE 'Equity%') 
WHERE rn = 1; 

Tuttavia, mi sono imbattuto i casi che la risposta della mia richiesta (senza smistamento per data) può apparire come quello:

+----------------------------------------------+ 
| TAG_VALUE TAG_DESC INSERTION_DATE PROJECT_ID | 
+----------------------------------------------+ 
| null  Equity 14-DEC-14  1  | 
| 0   Equity 14-DEC-14  1  | 
| 312   Equity 14-DEC-14  1  | 
| 23343  Equity 17-DEC-11  5  | 
| 1263  Equity 16-DEC-11  5  | 
| null  Equity 22-JÄN-14  2  | 
| null  Equity 11-JÄN-14  2  | 
| null  Equity 25-SEPT-13  2  | 
| 0   Equity 20-SEPT-13  2  | 
| 1234  Equity 19-SEPT-13  2  | 
| 13415  Equity 18-SEPT-13  2  | 
| 99999  Equity 16-OCT-10  9  | 
+----------------------------------------------+ 

mio Result Set dovrebbe essere simile che:

+----------------------------------------------+ 
| TAG_VALUE TAG_DESC INSERTION_DATE PROJECT_ID | 
+----------------------------------------------+ 
| 312   Equity 14-DEC-14  1  | 
| 23343  Equity 17-DEC-11  5  | 
| 1234  Equity 19-SEPT-13  2  | 
| 99999  Equity 16-OCT-10  9  | 
+----------------------------------------------+ 

Ci sono due casi, che fondamentalmente si concentrano sullo stesso problema:

  • Come potete vedere ci sono due casi, quando la project_id = 1 la data di inserimento è sempre la stessa. Tuttavia, con la mia domanda di cui sopra ho ancora null indietro a causa dello ordering. Come posso recuperare il numero 312 senza ottenere il valore null o il valore 0?
  • Se projectID = 2 ci sono diverse date di inserimento e le date precedenti hanno come elementi TAG_VALUEnull. Tuttavia, mi piacerebbe avere lo tagValue di | 1234 Equity 19-SEPT-13 2 |, perché è l'ultimo valore?

Come, posso praticamente ignorare i valori tutti null e anche 0 valori e solo prendere il numerica, che è maggiore di 0 valore con la prima data?

Ho davvero apprezzato la tua risposta!

+0

Si prega di correggere la richiesta: DAL progetto p DA aggiornato u – Rusty

+1

TAG_VALUE è un VARCHAR2 o un NUMERO? Sembra un modello EAV e, se stai usando un tipo di dati generico, la risposta sarà molto più complicata. –

+0

@JonHeller Il TAG_Value è NUMERICO. Cosa intendi per modello EAV? – mrquad

risposta

3

Considerando che il raggruppamento avviene all'interno PROJECT_ID per INSERTION_DATE DECR e TAG_VALUE positivo, ho ottimizzato le funzioni analitiche per ottenere il risultato. Questa potrebbe non essere una soluzione robusta, ma sicuramente ti aiuterà.

Setup dati:

CREATE TABLE Table1 
    ("TAG_VALUE" varchar2(5), "TAG_DESC" varchar2(6), "INSERTION_DATE" varchar2(10), "PROJECT_ID" int) 
; 

INSERT ALL 
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID") 
     VALUES (NULL, 'Equity', '14-DEC-14', 1) 
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID") 
     VALUES ('0', 'Equity', '14-DEC-14', 1) 
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID") 
     VALUES ('312', 'Equity', '14-DEC-14', 1) 
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID") 
     VALUES ('23343', 'Equity', '17-DEC-11', 5) 
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID") 
     VALUES ('1263', 'Equity', '16-DEC-11', 5) 
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID") 
     VALUES (NULL, 'Equity', '22-JÄN-14', 2) 
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID") 
     VALUES (NULL, 'Equity', '11-JÄN-14', 2) 
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID") 
     VALUES (NULL, 'Equity', '25-SEPT-13', 2) 
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID") 
     VALUES ('0', 'Equity', '20-SEPT-13', 2) 
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID") 
     VALUES ('1234', 'Equity', '19-SEPT-13', 2) 
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID") 
     VALUES ('13415', 'Equity', '18-SEPT-13', 2) 
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID") 
     VALUES ('99999', 'Equity', '16-OCT-10', 9) 
SELECT * FROM dual 
; 

Query:

SELECT tag_value, 
     tag_desc, 
     insertion_date, 
     project_id 
FROM (SELECT tag_value, 
       tag_desc, 
       insertion_date, 
       project_id, 
       Last_value(Decode(tag_value, 0, NULL, 
              tag_value) ignore nulls) 
       over ( 
        PARTITION BY project_id 
        ORDER BY insertion_date ROWS BETWEEN unbounded preceding AND 
       unbounded 
       following) new_tag_value 
     FROM table1) 
WHERE tag_value = new_tag_value; 

Risultato:

TAG_VALUE TAG_DESC INSERTION_DATE PROJECT_ID 
312   Equity  14-DEC-14  1 
1234  Equity  19-SEPT-13  2 
23343  Equity  17-DEC-11  5 
99999  Equity  16-OCT-10  9 

Ecco la fiddle

1

È possibile selezionare il min (Insertion_Date) e l'ID del progetto in una query interna dalla tabella e filtrarlo per Tag_Value <> Null. Quindi nella query esterna, inner entra nella tabella con questa query interna su project_id e inserttion_date.

+0

Potresti aggiungere un esempio con una query di esempio? Che cosa intendete esattamente per 'selezionare il min (Insertion_Date) e l'ID del progetto in una query interna dalla tabella e filtrarlo per Tag_Value <> Null. – mrquad

+0

Selezionare * dalla tabella join (selezionare PROJECT_ID, min (INSERTION_DATE) da tavolo dove Tag_Value <> Null gruppo per ID progetto) – Xion

+0

Select * dalla tabella t1 unirsi (Select PROJECT_ID, min (INSERTION_DATE) da tavolo dove Tag_Value <> Null gruppo per ID di progetto) t2 su t1.Project_id = t2.project_id e t1.insertion_date = t2.insertion_date la "tabella" qui può essere la tabella attuale o l'istruzione selezionata che hai menzionato nella domanda. – Xion

1

Caso d'uso 1:

Se ho capito i vostri casi d'uso in modo corretto, è possibile farlo tramite "priorità" dei non-null-non-zero tag_value -s nella clausola ordinazione del vostro funzione analitica come segue :

ROW_NUMBER() OVER (
    PARTITION BY p.proj_id 
    ORDER BY 
     CASE WHEN t.tag_value > 0 THEN 0 ELSE 1 END ASC, 
     u.update_as_of DESC 
) RN 

Questo, naturalmente, vi darà null -s o zeri in uscita ogni volta che non ci sono altri tag_value -s nella vostra partizione dati individuati dal p.proj_id.


Caso d'uso 2:

Se si vuole sbarazzarsi degli zeri e null -s completamente, si dovrà modificare la clausola di where della query (interno), invece:

WHERE t.tag_desc LIKE 'Equity%' 
    AND t.tag_value > 0 
3

La tua domanda è: "Come posso fondamentalmente ignorare tutti i valori nulli e anche 0 valori"

La risposta semplice è: rimuovendo quei record nella clausola WHERE.

Io uso AND t.tag_value > 0 qui. È possibile sostituirlo con AND t.tag_value <> 0 AND t.tag_value IS NOT NULL, se si desidera consentire valori negativi.

SELECT * 
FROM 
(
    SELECT 
    t.tag_value, 
    t.tag_desc, 
    u.update_as_of AS INSERTION_DATE, 
    p.proj_id AS PROJECT_ID, 
    ROW_NUMBER() OVER(PARTITION BY p.proj_id ORDER BY u.update_as_of DESC) RN 
    FROM updated u 
    JOIN project p ON p.project_id = u.project_id 
    JOIN tag t ON t.tag_id = u.tag_id 
    WHERE t.tag_desc LIKE 'Equity%' AND t.tag_value > 0 
) 
WHERE RN = 1; 
Problemi correlati