Oracle: Как получить значение по умолчанию, когда более конкретное значение равно нулю из того же запроса? - PullRequest
4 голосов
/ 21 июля 2010

Этот заголовок жестокий, но я не знаю, как еще его выразить.

У меня есть таблица значений ключей, привязанная к user_id, в котором хранятся настройки пользователя по всему сайту.Если пользователь не заходил и не обновлял какие-либо из своих настроек, каждый раз, когда я спрашиваю ключ (скажем, «FAVORITE_COLOR», он будет нулевым, поэтому мне нужно получить настройку по умолчанию, которую я привязал к пользователю по умолчанию,user_id = 0.

Я думал в духе UNION'а, что user_id = 0 приводит к нижней части запроса, но это может привести к дублированию. Я не уверен, возможно ли это вообщеНо что бы я хотел сказать, что-то вроде:

SELECT val FROM k_v WHERE user_id = 123 AND k = 'FAVORITE_COLOR'
UNION IF val IS NULL
SELECT val FROM k_v WHERE user_id = 0 AND k = 'FAVORITE_COLOR';

Любой хороший способ сделать это?

Редактировать: Спасибо за помощь в этом. Есливаш вариант использования только захватывает одно значение, каков этот вопрос, тогда NVL от dual - это именно то, что вам нужно, но если вы планируете возвращать несколько пар в одном запросе, взгляните на некоторые другие ответы.поскольку они могут на самом деле иметь больше смысла для реализации.

Я согласился с предложением ZeissS, приведенным ниже, поскольку он простой, все еще один запрос, работает с несколькими парами k, v, и у меня нет проблем с выполнениемвозможная двойная фильтрация на стороне клиента.

Ответы [ 4 ]

6 голосов
/ 21 июля 2010

Используйте это,

select
  nvl(
    (SELECT val FROM k_v WHERE user_id = 123 AND k = 'FAVORITE_COLOR'),
    (SELECT val FROM k_v WHERE user_id = 0 AND k = 'FAVORITE_COLOR')
  ) val 
from dual
;

Из документов Oracle,

NVL (expr1, expr2) : NVL позволяет заменить ноль (возвращается какпустым) со строкой в ​​результатах запроса.Если expr1 равен нулю, то NVL возвращает expr2.Если expr1 не ноль, то NVL возвращает expr1.

2 голосов
/ 21 июля 2010

Я хотел бы сделать что-то вроде этого:

SELECT k_v.v FROM k_v WHERE userid IN (:userid, 0) ORDER BY userid DESC

и использовать только первый возвращенный ряд.

2 голосов
/ 21 июля 2010

Вы, вероятно, можете оставить соединение и затем выбрать наиболее подходящий:

SELECT
  NVL(best.val, fallback.val) as val
FROM
  (SELECT val FROM k_v WHERE user_id = 0 AND k = 'FAVORITE_COLOR') as fallback
  left outer join (SELECT val FROM k_v WHERE user_id = 123 AND k = 'FAVORITE_COLOR') as best on 1 = 1

Не уверен в синтаксисе оракула, но вы, вероятно, могли бы заменить соединение "left external on 1 = 1" для какого-то взаимного соединения.

0 голосов
/ 21 июля 2010
SELECT nvl(k.k,kd.k) as k, 
       nvl(k.val, kd.val) as val 
FROM (select * from k_v where user_id = 0) kd 
     full outer join 
     (select * from k_v where user_id = 123) k 
     on kd.k = k.k 
WHERE 'FAVORITE_COLOR' in (k.k,kd.k)

Я предлагаю сделать полное внешнее объединение, потому что оно будет гарантировать результат, как при отсутствии значения по умолчанию, так и при отсутствии конкретного пользовательского результата. Если нет возможности пропустить значение по умолчанию, запрос можно немного упростить:

SELECT nvl(k_v.k,kd.k) as k, 
       nvl(k_v.val, kd.val) as val 
FROM k_v kd 
     left outer join k_v 
     on kd.k = k_v.k 
        and k_v.user_id = 123
WHERE kd.k = 'FAVORITE_COLOR'
  and kd.user_id = 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...