Как оценить строку на основе количества совпадений в запросе ИЛИ? - PullRequest
1 голос
/ 03 июля 2019

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

Это для postgres 9.1 (отредактировано) 11.1 и моя первоначальная попытка (на основе статьи о переполнении стека, которую я пытаюсь перефразировать) выглядела примерно так:

SELECT                                                                          
  T.id,                                                                         
  (                                                                             
    SELECT                                                                      
    count(*)                                                                    
    FROM (                                                                      
      VALUES                                                                    
        (T.criteria1),                                                               
        (T.criteria2),                                                              
        (T.criteria3),                                                      
        (T.criteria4)                                                              
    ) AS VALS(col)                                                              
    WHERE VALS.col IS NOT NULL                                                  
  ) AS score                                                                    
  FROM my_table AS T                                                     
  WHERE T.other_criteria = 'somevalue'                                                    
    AND (                                                                       
      T.criteria1='foo'                                                              
      OR T.criteria2='bar'                                                          
      OR T.criteria3 = 'baz                                                          
      OR T.criteria4 = 'stackoverflow'                                                        
    )                                                                           
    ORDER BY score DESC                                                         
    LIMIT 1;        

Сначала я думал, что это работает, но потом я понял, что на самом деле он просто складывал число ненулевых значений в строках, которые соответствуют моему ИЛИ. Вместо того, чтобы score был числом ненулевых столбцов, я хотел бы, чтобы он был числом столбцов, которые соответствуют условиям where.

Например, если у меня есть строка, которая соответствует 2 моим условиям ИЛИ, я бы хотел, чтобы она возвращала 2 балла, а если она соответствует 3 - 3 и т. Д.

Я пытался сделать что-то вроде следующего, но безрезультатно.

SELECT 
  T.id
 SUM(                                                                          
    (case when T.criteria1 = 'foo' then 1 else 0 end)  
    ...                              
  ) 
...

Любые идеи будут с благодарностью.

1 Ответ

1 голос
/ 03 июля 2019

Вы можете просто

ORDER BY (T.criteria1 IS NOT DISTINCT FROM 'foo')::integer
       + (T.criteria2 IS NOT DISTINCT FROM 'bar')::integer
       + (T.criteria3 IS NOT DISTINCT FROM 'baz')::integer
       + (T.criteria4 IS NOT DISTINCT FROM 'stackoverflow')::integer DESC
...