ORACLE LIKE с несколькими значениями

Вот три интересных способа

  1. Чтение по спирали можно рассматривать как змею, движущуюся к границе и включающую попадание границы или себя (я нахожу ее элегантной и наиболее эффективной, будучи одиночный цикл из N итераций)
    ar = [
         [ 0,  1,  2,  3, 4],
         [15, 16, 17, 18, 5],
         [14, 23, 24, 19, 6],
         [13, 22, 21, 20, 7],
         [12, 11, 10, 9, 8]]
    
    def print_spiral(ar):
        """
        assuming a rect array
        """
        rows, cols = len(ar), len(ar[0])
        r, c = 0, -1 # start here
        nextturn = stepsx = cols # move so many steps
        stepsy = rows-1
        inc_c, inc_r = 1, 0 # at each step move this much
        turns = 0 # how many times our snake had turned
        for i in range(rows*cols):
            c += inc_c
            r += inc_r 
    
            print ar[r][c],
    
            if i == nextturn-1:
                turns += 1
                # at each turn reduce how many steps we go next
                if turns%2==0:
                    nextturn += stepsx
                    stepsy -= 1
                else:
                    nextturn += stepsy
                    stepsx -= 1
                # change directions
                inc_c, inc_r = -inc_r, inc_c  
    
    print_spiral(ar)
    

output:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  1. Рекурсивным подходом было бы напечатать внешний слой и вызвать ту же функцию для внутреннего прямоугольник, например
    def print_spiral(ar, sr=0, sc=0, er=None, ec=None):
        er = er or len(ar)-1
        ec = ec or len(ar[0])-1
    
        if sr > er or sc > ec:
            print
            return
    
        # print the outer layer
        top, bottom, left, right = [], [], [], []
        for c in range(sc,ec+1):
            top.append(ar[sr][c])
            if sr != er:
                bottom.append(ar[er][ec-(c-sc)])
    
        for r in range(sr+1,er):
            right.append(ar[r][ec])
            if ec != sc:
                left.append(ar[er-(r-sr)][sc])
    
        print " ".join([str(a) for a in top + right + bottom + left]),
    
        # peel next layer of onion
        print_spiral(ar, sr+1, sc+1, er-1, ec-1)
    

Наконец, вот небольшой фрагмент, чтобы сделать это, но не эффективно, но весело :), в основном он печатает верхний ряд и вращает весь прямоугольник против часовой стрелки и повторяет

def print_spiral(ar):
    if not ar: return
    print " ".join(str(a) for a in ar[0]),
    ar = zip(*[ reversed(row) for row in ar[1:]])
    print_spiral(ar)
1
задан APC 18 March 2019 в 17:39
поделиться

4 ответа

из or_log_all_proc, or_proc, or_log, Patient

Ваш SELECT не содержит критериев объединения , поэтому он будет генерировать продукт из все записи из трех из этих таблиц и набор результатов любой таблицы фильтруются предложениями LIKE. Это корень вашей проблемы с производительностью.

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

Кстати, это преимущество использования синтаксиса соединения ANSI 92. Делая тип объединения явным, мы должны написать CROSS JOIN, если мы действительно хотим сгенерировать продукт, и не позволяет нам сделать это случайно.

Ожидать, что LIKE '% any%' будет быстрым, также бесполезно

До определенного момента. Скорее всего, это полное сканирование таблицы, но это индексированный столбец, тогда мы можем получить полное быстрое сканирование. Даже если это просто FTS, это не обязательно катастрофично, особенно если стол маленький или нарро. Как с большинством задач настройки, это действительно зависит от деталей.

0
ответ дан APC 18 March 2019 в 17:39
поделиться

LIKE все равно будет медленно, не так ли? Хотя, если вы уверены, что именно OR вызывает проблемы, попробуйте UNION, например

select pat_mrn_id,surgery_date, proc_name  
from or_log_all_proc, or_proc, or_log, patient
where upper(proc_name) like ('%CRANIOTOMY ANEURYSM%')
union all
select pat_mrn_id,surgery_date, proc_name  
from or_log_all_proc, or_proc, or_log, patient
where upper(proc_name) like ('CLIPPING%ANEURYSM')

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

0
ответ дан Littlefoot 18 March 2019 в 17:39
поделиться

Вместо LIKE используйте регулярные выражения. Но что более важно, вы пропускаете JOIN условия:

select pat_mrn_id,surgery_date, proc_name  
from or_log_all_proc join
     or_proc
     on ???? join
     or_log
     on ????
     patient
     on ????
where regexp_like(upper(proc_name), '(CRANIOTOMY ANEURYSM)|(CLIPPING.*ANEURYSM)');

Гораздо более вероятно, что проблема производительности связана с отсутствием JOIN условий, чем LIKE.

0
ответ дан Gordon Linoff 18 March 2019 в 17:39
поделиться

Попробуйте union all вместо or для лучшей производительности

 select pat_mrn_id,surgery_date, proc_name  
 from or_log_all_proc, or_proc, or_log, patient
 where 
 upper(proc_name) like ('CLIPPING%ANEURYSM')
 union all     
 select pat_mrn_id,surgery_date, proc_name  
 from or_log_all_proc, or_proc, or_log, patient
 where upper(proc_name) like ('%CRANIOTOMY ANEURYSM%')

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

0
ответ дан user7294900 18 March 2019 в 17:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: