2013-05-10 5 views
1

Я ищу лучший подход к написанию высоко повторяющихся операторов sql. Я знаю, что могу это сделать, например, используя PHP-методы, но я бы хотел получить чистое SQL-решение. Я использую Sybase.Лучшая практика повторения SQL-заявлений

select 
"SvHKeyId"=sh.KeyId, 
"Scale"="Partial PTSD", 
"ScoreText"=convert(varchar(3), 
    (case 
     when 
      (case 
       when 
        1 in (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum between 1 and 13) 
        and 1 in (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum between 15 and 21) 
        and 1 in (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum between 22 and 26) 
       then 'Yes' 
       else 'No' 
      end) 
     = 'Yes' 
     and 
     (case 
      when 
       (case 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=30) >= 2 
         or (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=32) >= 2 
         or (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=33) >= 2 
         or (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=29) >= 2 
         or (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=45) >= 2 
        then 1 
        else 0 
       end) 
       + 
       (case 
        when 
         (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=36) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=44) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=42) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=34) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=35) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) >= 2 then 1 else 0 end) 
        >= 3 then 1 
        else 0 
       end) 
       + 
       (case 
        when 
         (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=40) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=43) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=28) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=39) >= 2 then 1 else 0 end) 
        >= 2 then 1 
        else 0 
       end) 
      >=2 
      then 'Yes' 
      else 'No' 
     end) 
     = 'Yes' 
     then 'Yes' 
     else 'No' 
    end) 
    ), 
"ScoreNum"= 
    (case 
     when 
      (case 
       when 
        1 in (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum between 1 and 13) 
        and 1 in (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum between 15 and 21) 
        and 1 in (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum between 22 and 26) 
       then 'Yes' 
       else 'No' 
      end) 
     = 'Yes' 
     and 
     (case 
      when 
       (case 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=30) >= 2 
         or (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=32) >= 2 
         or (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=33) >= 2 
         or (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=29) >= 2 
         or (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=45) >= 2 
        then 1 
        else 0 
       end) 
       + 
       (case 
        when 
         (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=36) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=44) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=42) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=34) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=35) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) >= 2 then 1 else 0 end) 
        >= 3 then 1 
        else 0 
       end) 
       + 
       (case 
        when 
         (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=40) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=43) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=28) >= 2 then 1 else 0 end) 
         + (case when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=39) >= 2 then 1 else 0 end) 
        >= 2 then 1 
        else 0 
       end) 
      >=2 
      then 'Yes' 
      else 'No' 
     end) 
     = 'Yes' 
     then 1 
     else 0 
    end) 
from 
    SurvHeader sh 
where 
    sh.KeyId=105101 

Это процедура подсчета очков. Я сравниваю серию суб-оценок, чтобы получить общий балл. Есть ли лучший подход к SQL? Полагаю, я могу использовать хранимую процедуру?

Вот еще более экстремальный пример, где я использую так много подзапросов Я превышать предел:

select 
"SvHKeyId"=sh.KeyId, 
"Scale"="Total", 
"ScoreText"=convert(varchar(3), 
     (select sum(Resp) from SurvResp sr where sh.KeyId=sr.SvHKeyId 
     and QuestNum in (28,29,30,31,32,33,34,35,36,39,40,42,43,44,45,46) and Resp <> 5) 
     + 
     (case 
      when 
       (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) <> 5 
       and (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) <> 5 
      then 
       (case 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) 
         > (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) 
         < (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) 
         = (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) 
       end) 
      else 
       (case 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) = 5 
         and (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) = 5 
        then 0 
        else 
         (case 
          when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) = 5 
          then (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) 
          when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) = 5 
          then (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) 
          else 0 
         end) 
       end) 
     end) 
     + 
     (case 
      when 
       (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) <> 5 
       and (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) <> 5 
      then 
       (case 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) 
         > (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) 
         < (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) 
         = (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) 
       end) 
      else 
       (case 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) = 5 
         and (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) = 5 
        then 0 
        else 
         (case 
          when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) = 5 
          then (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) 
          when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) = 5 
          then (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) 
          else 0 
         end) 
       end) 
     end) 
     + 
     (case 
      when 
       (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) <> 5 
       and (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) <> 5 
      then 
       (case 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) 
         > (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) 
         < (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) 
         = (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) 
       end) 
      else 
       (case 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) = 5 
         and (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) = 5 
        then 0 
        else 
         (case 
          when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) = 5 
          then (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) 
          when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) = 5 
          then (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) 
          else 0 
         end) 
       end) 
     end) 
    ), 
"ScoreNum"= 
     (select sum(Resp) from SurvResp sr where sh.KeyId=sr.SvHKeyId 
     and QuestNum in (28,29,30,31,32,33,34,35,36,39,40,42,43,44,45,46) and Resp <> 5) 
     + 
     (case 
      when 
       (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) <> 5 
       and (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) <> 5 
      then 
       (case 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) 
         > (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) 
         < (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) 
         = (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) 
       end) 
      else 
       (case 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) = 5 
         and (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) = 5 
        then 0 
        else 
         (case 
          when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) = 5 
          then (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) 
          when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=38) = 5 
          then (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=37) 
          else 0 
         end) 
       end) 
     end) 
     + 
     (case 
      when 
       (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) <> 5 
       and (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) <> 5 
      then 
       (case 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) 
         > (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) 
         < (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) 
         = (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) 
       end) 
      else 
       (case 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) = 5 
         and (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) = 5 
        then 0 
        else 
         (case 
          when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) = 5 
          then (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) 
          when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=47) = 5 
          then (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=31) 
          else 0 
         end) 
       end) 
     end) 
     + 
     (case 
      when 
       (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) <> 5 
       and (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) <> 5 
      then 
       (case 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) 
         > (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) 
         < (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) 
         = (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) 
        then 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) 
       end) 
      else 
       (case 
        when 
         (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) = 5 
         and (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) = 5 
        then 0 
        else 
         (case 
          when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) = 5 
          then (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) 
          when (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=48) = 5 
          then (select Resp from SurvResp sr where sh.KeyId=sr.SvHKeyId and sr.QuestNum=46) 
          else 0 
         end) 
       end) 
     end) 
from 
    SurvHeader sh 
where sh.KeyId=105101 
+1

«Я бы хотел получить чистое SQL-решение» - почему? то, что вы сейчас делаете, в значительной степени нечитаемо ... –

+0

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

+0

И аналогично, вы можете сказать, что этот код SQL очень утомительный, перемещение логики в приложение создало бы решение, которое не зависит от механизма SQL ... Или, короче говоря, это сводится к следующему: нужна ли вам эта независимость ? –

ответ

2

Большинство из этих литералов должны быть данные, а не код. Я настоятельно рекомендую реорганизовать эти гигантские коммутаторы в данные, поэтому более простой запрос может его оценить. Тогда решение «чистого SQL» было бы намного более выполнимо, и производительность и обслуживание в конечном итоге будут лучше. Может быть, таблица Scoring, к которой вы можете присоединиться и сравнить?

Scoring (Question, Answer, Result) - одна концептуальная возможность, надеюсь, не слишком упрощенная.

Как уже было сказано, "You can write FORTRAN in any language."

Даже T-SQL, это кажется.

UPDATE

Если эти расчеты уже сделаны, и вы обновили таблицы в пределах текущей транзакции, нет необходимости заново делать их просто потому, что они еще не совершили. Любой запрос в рамках этой транзакции получит обновленные данные этой транзакции, если она была обновлена ​​ранее в транзакции.

Подробнее о Sybase ASE transactions.

Кроме того, вы не должны ожидать GO до work in a stored procedure. Он используется в качестве разделителя партий в вашей среде IDE, а не для управления транзакциями.

+0

Фактически они сохраняются как данные в таблице подсчета очков - предыдущие запросы генерируют оценки для одних и тех же подкатегорий в предыдущем выражении. Возможно, моя глупость делала это в той же транзакции, потому что я не могу выбрать результат до завершения транзакции, поэтому я имел избыточность. Есть ли способ выбрать значение из транзакции, которая еще не совершена, когда вы находитесь в той же транзакции? В противном случае я могу потенциально иметь сиротские значения, если я использую отдельные транзакции, и что-то пойдет не так. – MaxPowers

+0

Мне все равно кажется, что вы хотите представить все эти 'case' как строки в таблице. –

+0

Пока вы находитесь внутри транзакции, все предыдущие изменения, сделанные в рамках этой транзакции, будут видны вам. –

Смежные вопросы