2009-09-18 7 views
0

Dans la réponse à un article précédent (Tuning Rows-to-Cols Query), j'ai appris à construire plus efficacement une requête de ligne à colonne qui permet le filtrage par date. Cependant, je dois maintenant aller plus loin.Réglage de la requête de lignes à plusieurs niveaux à plusieurs niveaux

Le schéma ci-dessous pour la requête est la suivante:
SAMPLE (1-to-many) TEST (1-to-many) RESULT (1-to-MANY)
Chaque échantillon a un ou plusieurs tests, et chaque test a un ou plusieurs résultats.

Question: Comment est-ce que je peux réécrire cette vue plus efficacement, permettant toujours le filtrage rapide par "date samplée?"

Concern: Les points MAX(tst.created_on) devraient être l'ensemble des essais uniques avec test_id (set 1) non pas pour l'ensemble des résultats uniques avec test_id (set 2):

set 1: {1, 2, 76,  77,  135,  136} 
set 2: {1, 1, 2, 2, 76, 76, 77, 77, 135, 135, 136, 136}
CREATE OR REPLACE VIEW V_TITRATION_SAMPLES as 
    SELECT sam.sampled_on "Date Sampled", 
      MAX(CASE WHEN res.result_tmpl_id = 4 THEN result END) "titrator", 
      MAX(CASE WHEN res.result_tmpl_id = 3 THEN result END) "factor", 
      MAX(tst.created_on) "Last Test Creation" 
     FROM lims.sample sam 
     JOIN lims.test tst ON sam.sample_id = tst.sample_id 
     JOIN lims.result res ON tst.test_id = res.test_id 
     WHERE sam.sample_tmpl_id = 4 
    GROUP BY sample_id, sam.sampled_on 

avant GROUP BY:

SAMPLE COLUMNS  | TEST COLUMNS  | RESULT COLUMNS 
    id tmp sampled_on | *id tmp created_on | *id tmp result 
    1 4 09-20 21:50 | 1 7 09-20 22:20 | 1 1  5 
    1 4 09-20 21:50 | 1 7 09-20 22:20 | 2 3 2.1 
    1 4 09-20 21:50 | 2 9 09-20 22:23 | 3 4  6 
    1 4 09-20 21:50 | 2 9 09-20 22:23 | 4 6 123 

    25 4 09-21 08:26 | 76 7 09-21 08:53 | 96 1  4 
    25 4 09-21 08:26 | 76 7 09-21 08:53 | 97 3 1.6 
    25 4 09-21 08:26 | 77 9 09-21 08:52 | 98 4  4 
    25 4 09-21 08:26 | 77 9 09-21 08:52 | 99 6 103 

    102 4 09-21 09:54 | 135 7 09-21 10:34 | 185 1  1 
    102 4 09-21 09:54 | 135 7 09-21 10:34 | 186 3 1.8 
    102 4 09-21 09:54 | 136 9 09-21 10:05 | 187 4  5 
    102 4 09-21 09:54 | 136 9 09-21 10:05 | 188 6 110 

* Shortened TABLE_id and TABLE_template_id to id and tmp, 
    respectively to keep this data grid narrow. 

Résultats:

"Date Sampled" titrator factor "Last Test Creation" 
    09-20 21:50  6   2.1 09-20 22:23 
    09-21 08:26  4   1.6 09-21 08:53 
    09-21 09:54  5   1.8 09-21 10:34 
+2

Je ne suis pas sûr que je comprends ce que « ne doit être vérifiée à travers les tests de l'échantillon ne concernent pas tous les résultats de tous les tests effectués dans l'échantillon "signifie dans ce contexte. Pouvez-vous potentiellement montrer un échantillon des données et nous montrer votre production attendue? Mon pari à ce stade est que la solution impliquera des fonctions analytiques, mais je ne suis pas sûr de ce que vous recherchez, donc je ne suis pas sûr de la fonction à proposer. –

+0

La description du schéma n'est pas claire. Et pouvez-vous (1) utiliser des alias pour toutes les tables et (2) remplacer les clauses "using" par "on"? –

+0

J'ai simplifié la question principale. Cela devrait être plus clair maintenant. – Steven

Répondre

0

Donnez ce un coup:

WITH titrate AS (
    SELECT r.test_id, 
      MAX(r.result) 'titrator' 
     FROM LIMS.RESULT r 
     WHERE r.result_tmpl_id = 4 
    GROUP BY r.test_id), 
    factor AS (
    SELECT r.test_id, 
      MAX(r.result) 'factor' 
     FROM LIMS.RESULT r 
     WHERE r.result_tmpl_id = 3 
    GROUP BY r.test_id), 
    created AS (
    SELECT t.sample_id, 
      MAX(t.created_on) 'created' 
     FROM LIMS.TEST t 
    GROUP BY t.sample_id) 
    SELECT s.sampled_on, 
      ti.titrator, 
      f.factor, 
      t.created 
    FROM LIMS.SAMPLE s 
    JOIN created t ON t.sample_id = s.sample_id 
LEFT JOIN titrate ti ON ti.test_id = t.test_id 
LEFT JOIN factor f ON f.test_id = t.test_id 

j'ai changé les déclarations de cas en utilisant l'affacturage sous-requête - la LEFT JOIN peut ne pas être nécessaire.

La partie clé est la vue en ligne/affacturage sous-requête pour la table LIMS.TEST, où vous voulez obtenir la date created_on max pour une sample_id - séparant du reste de la requête vous donnera plus de contrôle pour retourner ce vous voulez spécifiquement de cette table.

L'alternative équivalente à l'aide des vues inline - ils effectuent la même, juste que l'affacturage sous-requête est uniquement prise en charge depuis 9i:

SELECT s.sampled_on, 
      ti.titrator, 
      f.factor, 
      t.created 
    FROM LIMS.SAMPLE s 
    JOIN (SELECT t.sample_id, 
        MAX(t.created_on) 'created' 
      FROM LIMS.TEST t 
     GROUP BY t.sample_id) t ON t.sample_id = s.sample_id 
LEFT JOIN (SELECT r.test_id, 
        MAX(r.result) 'titrator' 
      FROM LIMS.RESULT r 
      WHERE r.result_tmpl_id = 4 
     GROUP BY r.test_id) ti ON ti.test_id = t.test_id 
LEFT JOIN (SELECT r.test_id, 
        MAX(r.result) 'factor' 
      FROM LIMS.RESULT r 
      WHERE r.result_tmpl_id = 3 
     GROUP BY r.test_id) f ON f.test_id = t.test_id 
Questions connexes