2012-01-19 2 views
1

У меня возникают проблемы с запросом «advanced» (по моим стандартам) в Postgresql, и я не уверен, как мне искать ответ (ключевые слова и т. Д.). Я просмотрел примеры в справочнике Postgresql и искал stackOverflow для подобных потоков, но безуспешно ...postgresql запрос с AND/OR/UNION

У меня есть две таблицы: одна с векселями и одна с транзакциями, а таблица, которую я хотел бы выводить, содержит только те транзакции, которые являются 1) более поздними, чем счет, 2) ниже или равным счету 3) на определенном счете или оплачиваются наличными.

Этот запрос делает именно это, но я предполагаю, что это может быть оптимизировано:

((SELECT * FROM transactions 
WHERE amount = to_number('$bill_amount','99999999D99') 
AND acc_int = 'cash' 
AND date > to_date('$bill_date', 'YYYY-MM-DD')) 
UNION 
(SELECT * FROM transactions 
WHERE amount = to_number('$bill_amount','99999999D99') 
AND acc_int = 'xxx-xxxxxxx-xx' 
AND date > to_date('$bill_date', 'YYYY-MM-DD')) 
ORDER BY date DESC) 
UNION 
((SELECT * FROM transactions 
WHERE amount < to_number('$bill_amount','99999999D99') 
AND acc_int = 'cash' 
AND date > to_date('$bill_date', 'YYYY-MM-DD')) 
UNION 
(SELECT * FROM transactions 
WHERE amount < to_number('$bill_amount','99999999D99') 
AND acc_int = 'xxx-xxxxxxx-xx' 
AND date > to_date('$bill_date', 'YYYY-MM-DD')) 
ORDER BY date DESC) 

Первые два выбирает могут быть объединены, если я мог бы просто добавить OR к «acc_int'-состоянии, не нарушая другой условия. Я думал, что это нужно сделать, используя скобки, но, похоже, это не сработало.

Кроме того, я хотел бы отсортировать результат так, чтобы сначала все транзакции равны сумме на счете, а затем, по дате, более низкие суммы - вот почему я совмещаю первые два выбора с двумя последними выборами, но используя UNION похоже, нарушает порядок.

THX для любой проницательности (ответы или ссылки на хорошие ресурсы оба приветствуются!)

ответ

1

Полный запрос может выглядеть следующим образом:

SELECT * 
FROM transactions 
WHERE amount <= to_number('$bill_amount','99999999D99') 
AND acc_int IN ('cash', 'xxx-xxxxxxx-xx') 
AND date > to_date('$bill_date', 'YYYY-MM-DD') 
ORDER BY 
     (amount <> to_number('$bill_amount','99999999D99')) 
    , date DESC 
  • FALSE до TRUE, поэтому у меня есть t он <> оператор в выражении ORDER BY.

  • Помните, что в вашем исходном запросе UNION удаляет повторяющиеся строки. Если у вас нет полных дубликатов в таблице, результат будет таким же (и UNION ALL был бы лучшим выбором для начала). Если да, то добавьте DISTINCT пункт:

    SELECT DISTINCT * ... 
    
  • Вы пишете, что OR не похоже на работу для вас. Но это должно быть. Это ..

    AND acc_int IN ('cash', 'xxx-xxxxxxx-xx') 
    

    .. в точности эквивалентно:

    AND (acc_int = 'cash' OR acc_int = 'xxx-xxxxxxx-xx') 
    

В самом деле планировщик запросов переписывает первую форму в секунду.

+0

THX - это один - он отлично работает. Я знал, что это можно сделать, но сдерживается 1 ошибкой (OR-предложение, вероятно, было ошибочно записано, потому что я думаю, что я попробовал это так, как вы описали) и 1 вещь, которую я даже не знал (выражения в ORDER BY- инструкция). – zenlord

1

Что-то вроде этого, возможно:

SELECT * FROM transactions 
WHERE amount <= to_number('$bill_amount','99999999D99') 
AND acc_int IN ('cash', 'xxx-xxxxxxx-xx') 
AND date = to_date('$bill_date', 'YYYY-MM-DD') 
ORDER BY date DESC 
+0

Благодарим вас, что ваш ответ эффективно сократил запрос пополам (условие суммы изменено на «ГДЕ» МЕЖДУ 0 И $ bill_amount », чтобы избежать отрицательных результатов. Остается только вопрос о порядке сортировки: Точные суммы-совпадения сверху и снизу/частичные суммы ниже. – zenlord

+0

Вы можете заказать по сумме, также –

+0

Да, я знал это, и я полностью забыл об этом. Спасибо за ваш ответ! – zenlord