Сложный расчет с использованием Oracle SQL - PullRequest
3 голосов
/ 02 марта 2011

Я создал базу данных для воображаемых адвокатов, мой последний запрос сводит меня с ума.Мне нужно определить сумму, которую адвокат заработал в своей карьере в компании, у меня есть time_spent и rate для умножения и специальная ставка для прибавления.(по корпоративным контрактам действует специальная ставка, поэтому не во многих случаях они есть).лучшее, что я мог придумать, это код ниже.Он делает то, что я хочу, но отображает только солиситоры, работающие с делом, к которому применена специальная ставка.

Я хочу, чтобы он отображал результат запроса в таблице, даже если специальная ставка равна NULL.

Я приказал таблице сначала показать наибольшую сумму, чтобы я мог использовать ROWNUM, чтобы показывать только 10% получателей.

CREATE VIEW rich_solicitors AS 
  SELECT notes.time_spent * rate.rate_amnt + special_rate.s_rate_amnt AS solicitor_made,          
        notes.case_id
   FROM notes, 
        rate, 
        solicitor_rate, 
        solicitor, 
        case, 
        contract, 
        special_rate
  WHERE notes.solicitor_id = solicitor.solicitor_id
    AND solicitor.solicitor_id = solicitor_rate.solicitor_id
    AND solicitor_rate.rate_id = rate.rate_id
    AND notes.case_id = case.case_id
    AND case.contract_id = contract.contract_id
    AND contract.contract_id = special_rate.contract_id
ORDER BY -solicitor_made;

Запрос:

SELECT * 
  FROM rich_solicitors
 WHERE ROWNUM <= (SELECT COUNT(*)/10 
                    FROM rich_solicitors)

Ответы [ 2 ]

5 голосов
/ 02 марта 2011

Я подозреваю, что вы используете ROWNUM в своем примере запроса ...

Oracle9i + поддерживает аналитические функции, такие как ROW_NUMBER и NTILE , чтобы упростить запросы, подобные вашему примеру.Аналитика также является ANSI, поэтому синтаксис при реализации согласован (IE: не в MySQL или SQLite).Я переписал ваш запрос следующим образом:

SELECT x.*
  FROM (SELECT n.time_spent * r.rate_amnt + COALESCE(spr.s_rate_amnt, 0) AS solicitor_made,          
               n.case_id,
               NTILE(10) OVER (ORDER BY solicitor_made) AS rank
          FROM NOTES n 
          JOIN SOLICITOR s ON s.solicitor_id = n.solicitor_id
          JOIN SOLICITOR_RATE sr ON sr.solicitor_id = s.solicitor_id 
          JOIN RATE r ON r.rate_id = sr.rate_id
          JOIN CASE c ON c.case_id = n.case_id 
          JOIN CONTRACT cntrct ON cntrct.contract_id = c.contract_id
     LEFT JOIN SPECIAL_RATE spr ON spr.contract_id = cntrct.contract_id) x
 WHERE x.rank = 1

Если вы новичок в SQL, я рекомендую использовать синтаксис ANSI-92.В вашем примере используется ANSI-89, который не поддерживает OUTER JOIN и считается устаревшим.Я использовал LEFT OUTER JOIN против таблицы SPECIAL_RATE, потому что не всем заданиям, вероятно, назначена специальная скорость.

Также не рекомендуется включать ORDER BY в представления, потому что представления инкапсулируют запрос -никто не будет знать, каков порядок по умолчанию, и, вероятно, будет включать их собственные (потенциально трата ресурсов).

3 голосов
/ 02 марта 2011

вам нужно оставить присоединиться к специальному тарифу.

Если я вспомню, синтаксис оракула выглядит так:

AND contract.contract_id = special_rate.contract_id (+) 

но теперь special_rate. * Может быть нулевым, поэтому:

+ special_rate.s_rate_amnt

должно быть:

+ coalesce(special_rate.s_rate_amnt,0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...