2017-12-19 1 views
0

Ich habe Daten über Projekte in verschiedenen Ländern. Jedes Projekt hat einen devlevel, ein sector und subsector, zum Beispiel (vereinfacht):Lookup basierend auf drei Kriterien, mit Fallback-Werte für zwei

pid |     sector     |  subsector  | devlevel 
------+------------------------------------------+----------------------+---------- 
    612 | Transport        | Airports & Logistics | EM 
1473 | Information & Communication Technologies | Broadband   | RoW 
1424 | Other         | Other    | RoW 
1476 | Transport        | Urban Highways  | RoW 
1443 | Water         | Water Supply   | EM 

auf die Kombination dieser drei Eigenschaften Je jedes Projekt hat eine gewisse efficiency.

sector |  subsector  | devlevel | efficiency 
-----------+--------------------+----------+------------ 
Transport | (null)    | EM  |  16000 
Transport | (null)    | RoW  |  9600 
Water  | (null)    | EM  |  16000 
Water  | (null)    | RoW  |  9600 
Energy | Generation — Hydro | EM  |  16000 
Energy | Generation — Hydro | RoW  |  9600 
Energy | (null)    | EM  |  11200 
Energy | (null)    | RoW  |  6720 
(null) | (null)    | EM  |  8000 
(null) | (null)    | RoW  |  8000 

Die Logik ist: wenn das Projekt ein sector und subsector Spiel hat, um seine devlevel die efficiency entsprechende Verwendung für den Augenblick habe ich die Lookup-Tabelle wie folgt strukturiert. Wenn es eine sector Übereinstimmung aber nicht subsector hat, verwenden Sie die efficiency entsprechend devlevel und subsectorNULL. Und wenn es keine Übereinstimmung über sector überhaupt gibt, verwenden Sie die efficiency mit sector und subsector Werte von NULL.

Ich hatte Mühe, eine Abfrage zu implementieren, die die relevanten efficiency nachschaut. Mein letzter Versuch ist unten. Es versucht, die möglichen Lookup-Werte basierend auf sector in einer anfänglichen Unterabfrage einzugrenzen, dann basierend auf subsector in einer nachfolgenden (übergeordneten) Unterabfrage weiter einzugrenzen und dann die abgespeckte Nachschlagetabelle mithilfe einer Übereinstimmung auf devlevel mit den Projektdaten zu verbinden . Aber ich bekomme diese Fehlermeldung:

ERROR: invalid reference to FROM-clause entry for table "p" 
LINE 26:     SELECT 1 FROM devlookup d1 WHERE p.sector = ... 
                 ^
HINT: There is an entry for table "p", but it cannot be referenced from this part of the query. 
SQL state: 42P01 
Character: 4079 

Zeiger würden sehr geschätzt werden.

Abfrage:

WITH devlookup (id, sector, subsector, devlevel, efficiency) 
AS (VALUES 
    (1, 'Transport', NULL, 'EM', 16000), 
    (2, 'Transport', NULL, 'RoW', 9600), 
    (3, 'Water', NULL, 'EM', 16000), 
    (4, 'Water', NULL, 'RoW', 9600), 
    (5, 'Energy', 'Generation — Hydro', 'EM', 16000), 
    (6, 'Energy', 'Generation — Hydro', 'RoW', 9600), 
    (7, 'Energy', NULL, 'EM', 11200), 
    (8, 'Energy', NULL, 'RoW', 6720), 
    (9, NULL, NULL, 'EM', 8000), 
    (10, NULL, NULL, 'RoW', 8000) 
), 
EMcountries AS (VALUES ('United Arab Emirates'), ('Afghanistan'), ('Antigua and Barbuda'), ('Anguilla'), ('Armenia'), ('Netherlands Antilles'), ('Angola'), ('Antarctica'), ('Argentina'), ('American Samoa'), ('Aruba'), ('Azerbaijan'), ('Barbados'), ('Bangladesh'), ('Burkina'), ('Bahrain'), ('Burundi'), ('Benin'), ('Brunei'), ('Bolivia'), ('Brazil'), ('Bahamas'), ('Bhutan'), ('Bouvet Island'), ('Botswana'), ('Belarus'), ('Belize'), ('Cocos (Keeling) Islands'), ('Congo {Democratic Rep}'), ('Central African Republic'), ('Congo'), ('Ivory Coast'), ('Cook Islands'), ('Chile'), ('Cameroon'), ('China'), ('Colombia'), ('Costa Rica'), ('Cuba'), ('Cape Verde'), ('Christmas Island'), ('Djibouti'), ('Dominica'), ('Dominican Republic'), ('Algeria'), ('Ecuador'), ('Egypt'), ('Western Sahara'), ('Eritrea'), ('Ethiopia'), ('Fiji'), ('Falkland Islands (Malvinas)'), ('Micronesia), (Federated States of'), ('Gabon'), ('Grenada'), ('Georgia'), ('French Guiana'), ('Ghana'), ('Gambia'), ('Guinea'), ('Guadeloupe'), ('Equatorial Guinea'), ('South Georgia and the South Sandwich Islands'), ('Guatemala'), ('Guam'), ('Guinea-Bissau'), ('Guyana'), ('Heard Island and McDonald Islands'), ('Honduras'), ('Haiti'), ('Indonesia'), ('India'), ('British Indian Ocean Territory'), ('Iraq'), ('Iran'), ('Jamaica'), ('Jordan'), ('Kenya'), ('Kyrgyzstan'), ('Cambodia'), ('Kiribati'), ('Comoros'), ('Saint Kitts and Nevis'), ('Korea), (Democratic People''s Republic of'), ('Kuwait'), ('Cayman Islands'), ('Kazakhstan'), ('Lao People''s Democratic Republic'), ('Lebanon'), ('St Lucia'), ('Sri Lanka'), ('Liberia'), ('Lesotho'), ('Libya'), ('Morocco'), ('Madagascar'), ('Marshall Islands'), ('Mali'), ('Myanmar), ({Burma}'), ('Mongolia'), ('Northern Mariana Islands'), ('Martinique'), ('Mauritania'), ('Montserrat'), ('Mauritius'), ('Maldives'), ('Malawi'), ('Mexico'), ('Malaysia'), ('Mozambique'), ('Namibia'), ('New Caledonia'), ('Niger'), ('Norfolk Island'), ('Nigeria'), ('Nicaragua'), ('Nepal'), ('Nauru'), ('Niue'), ('Oman'), ('Panama'), ('Peru'), ('French Polynesia'), ('Papua New Guinea'), ('Philippines'), ('Pakistan'), ('Pitcairn Islands'), ('Puerto Rico'), ('Palestinian Territory'), ('Palau'), ('Paraguay'), ('Qatar'), ('Reunion'), ('Rwanda'), ('Saudi Arabia'), ('Solomon Islands'), ('Seychelles'), ('South Sudan'), ('Sudan'), ('Saint Helena'), ('Sierra Leone'), ('Senegal'), ('Somalia'), ('Suriname'), ('Sao Tome & Principe'), ('El Salvador'), ('Syria'), ('Swaziland'), ('Turks and Caicos Islands'), ('Chad'), ('French Southern Territories'), ('Togo'), ('Thailand'), ('Tajikistan'), ('Tokelau'), ('Turkmenistan'), ('Tunisia'), ('Tonga'), ('Timor-Leste'), ('Trinidad & Tobago'), ('Tuvalu'), ('Tanzania'), ('Ukraine'), ('Uganda'), ('United States Minor Outlying Islands'), ('Uruguay'), ('Uzbekistan'), ('Saint Vincent and the Grenadines'), ('Venezuela'), ('Virgin Islands), (British'), ('Virgin Islands), (U.S.'), ('Vietnam'), ('Vanuatu'), ('Wallis and Futuna'), ('Samoa'), ('Yemen'), ('Mayotte'), ('South Africa'), ('Zambia'), ('Zimbabwe'), ('Saint Barthelemy'), ('Saint Martin')), 
projectinfo AS (
    SELECT p.pid, p.country, p.projectname, p.sector, p.subsector, 
     (CASE WHEN p.country IN (SELECT * FROM EMcountries) THEN 'EM' ELSE 'RoW' END) AS devlevel 
    FROM exp_projects p 
    ) 
SELECT p.pid, p.country, p.projectname, p.sector, p.subsector, p.devlevel, d.sector devsector, d.subsector devsubsector, d.efficiency 
FROM projectinfo p 
LEFT OUTER JOIN (
    SELECT * FROM (
     SELECT * FROM devlookup WHERE id IN (
      CASE WHEN EXISTS (
       SELECT 1 FROM devlookup d1 WHERE p.sector = d1.sector 
       ) 
      THEN (SELECT id FROM devlookup d1 WHERE d1.sector = p.sector) 
      ELSE (SELECT id FROM devlookup d1 WHERE d1.sector IS NULL) 
      END 
     ) 
    ) AS devlookup_matching_sector 
    WHERE id IN (
     CASE WHEN EXISTS (
      SELECT 1 FROM devlookup_matching_sector dms WHERE dms.subsector = p.subsector 
      ) 
     THEN (SELECT id FROM devlookup_matching_sector dms WHERE dms.subsector = p.subsector) 
     ELSE (SELECT id FROM devlookup_matching_sector dms WHERE dms.subsector IS NULL) 
     END 
    ) 
) devlookup_matching_sector_subsector 
ON (devlookup_matching_sector_subsector.devlevel = p.devlevel) 
WHERE p.country IN ('Australia', 'Afghanistan', 'Brazil') 
ORDER BY pid ASC; 
+0

Zeiger; LINKS VERBINDEN Sie Ihre Effizienz Tabelle 3 Mal mit abnehmender Spezifität, und verwenden Sie Koaleszenz, um die spezifischste Effizienz zu wählen –

Antwort

0

Ich habe Ihre Hauptabfrage hier nicht geändert, nur einen Mechanismus Demonstrieren die am besten zutreffende spezifische Effizienz gefunden zu wählen:

SELECT 
    p.*, 
    COALESCE(mostspecific.efficiency, midspecific.efficiency, leastspecific.efficiency) as best_e 
FROM 
    Project p 
    LEFT JOIN 
    Efficiency mostspecific 
    ON 
    p.devlevel = mostspecific.devlevel AND 
    p.sector = mostspecific.sector AND 
    p.subsector = mostspecific.subsector 

    LEFT JOIN 
    Efficiency midspecific 
    ON 
    p.devlevel = midspecific.devlevel AND 
    p.sector = midspecific.sector AND 
    midspecific.subsector IS NULL 

    LEFT JOIN 
    Efficiency leastspecific 
    ON 
    p.devlevel = leastspecific.devlevel AND 
    leastspecific.sector IS NULL AND 
    leastspecific.subsector IS NULL 

Die Logik, weil das Werk JOINs werden unterschiedlich erfolgreich sein .. die am wenigsten spezifischen sollten die ganze Zeit übereinstimmen, sollte die Med viele Male, und die meisten, ein paar Mal tun. Koaleszieren wählt das erste nicht null von links nach rechts aus, so dass die Effizienzen in der Reihenfolge des wahrscheinlichsten Fehlers (null sein) gesetzt werden, so dass das am relevantesten spezifische ausgewählt werden sollte:

+0

Dies ist wirklich eine Sache der Schönheit. Vielen Dank! – mpavey

Verwandte Themen