Определен ли результат предложения OR в SQL SELECT? - PullRequest
0 голосов
/ 29 ноября 2018

Я имею в виду следующее:

Если у меня есть инструкция SELECT следующим образом:

SELECT * FROM TAB1 WHERE COL1 = ('VAL1' OR 'VAL2') AND ...

Если в рассматриваемой таблице есть записи как для 'VAL1', так и для 'VAL2',порядок в предложении WHERE имеет какое-либо значение?

Если я предпочел бы вернуть запись с помощью 'VAL1', но взял бы 'VAL2', если первый не доступен, будет ли вышеупомянутый SELECT гарантировать это?Или ответ не определен в этом случае?И будет ли это поведение, кроме того, зависеть от поставщика?

Ответы [ 5 ]

0 голосов
/ 30 ноября 2018

Все условия в предложении WHERE применяются одновременно в SQL.Там нет порядка, гарантированного или подразумеваемого вообще.Это справедливо для любой СУБД SQL, а не только для SAP HANA.

Чтобы иметь взвешенный критерий выбора, необходимо создать весовую функцию, как указано в других ответах.Один из подходов, который довольно легко реализовать, состоит в том, чтобы сначала создать SELECT s для всех возможных весов, а затем выбрать записи с наибольшим / наименьшим весом.

Например:

WITH weighted AS ( 
 SELECT 100 as SEL_WEIGHT, PK1, PK2 
 FROM TAB1 WHERE COL1 = 'VAL1'
UNION ALL
 SELECT 60 as SEL_WEIGHT, PK1, PK2 
 FROM TAB1 WHERE COL1 = 'VAL2'
UNION ALL
 SELECT -1 as SEL_WEIGHT, PK1, PK2 
 FROM TAB1 WHERE COL1 IS NULL)

SELECT 
     * 
FROM 
    weighted 
WHERE (PK1, PK2, SEL_WEIGHT) in
      (SELECT PK1, PK2, MAX(SEL_WEIGHT) as MAX_WEIGHT
       FROM weighted
       GROUP BY PK1, PK2);

В этом примере подвыбор находит максимальный вес и соответствующие столбцы первичного ключа (PK1, PK2) и присоединяет их обратно в качестве окончательного критерия выбора к основному SELECT.Записи с COL1 ='VAL1' имеют самый высокий вес (100) и предпочтительнее записей с COL1='VAL2' (60) или тех, где COL1 равно NULL (-1).

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

Поскольку взвешенные критерии выбора не являютсястандарт в системах SQL, я настоятельно рекомендую сделать реализацию как можно более очевидной, чтобы избежать путаницы и недопонимания в дальнейшем.

0 голосов
/ 29 ноября 2018

Я бы выбрал ранжирование результатов на основе предпочтений, а затем выбирал записи, которые являются наиболее предпочтительными, как показано ниже

SELECT * FROM (
SELECT *,ROW_NUMBER() OVER(order by case when col1='VAL1' then 1 
                                         when col1='VAL2' then 2
                                    end asc) as rnk  
  FROM TAB1 
 WHERE COL1 = ('VAL1' OR 'VAL2') 
 )X
WHERE X.RNK=1
0 голосов
/ 29 ноября 2018

Нет, вы не можете сделать это таким образом, это может вернуть неправильную запись в зависимости от того, где и в каком порядке.

Попробуйте:

SELECT * FROM TAB1 
WHERE (COL1 = 'VAL1' OR (COL1 = 'VAL2' and (select count(*) from tab1 where COL1 = 
'VAL1') = 0)) AND ...
0 голосов
/ 29 ноября 2018

Do UNION ALL.Пусть первые SELECT возвращают строки VAL1.Есть еще один SELECT, который возвращает строки VAL2, но только в том случае, если строк VAL1 не существует.

SELECT * FROM TAB1
WHERE COL1 = 'VAL1'
union all
SELECT * FROM TAB1
WHERE COL1 = 'VAL2'
  and NOT EXISTS (SELECT * FROM TAB1 WHERE COL1 = 'VAL1')

По сути то же самое, что и ответ @Claudio Biselli, но его проще оптимизировать.

0 голосов
/ 29 ноября 2018

Возможно использовать IN вместо ИЛИ

Например:

SELECT * FROM TAB1 WHERE COL1 IN ('VAL1','VAL2') AND ...
...