2013-05-10 120 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解決方案」 - 爲什麼?你目前所做的幾乎是不可讀的...... – 2013-05-10 17:24:13

+0

也許純粹的SQL不是一種可行的方式。我想探索這個的原因是,使用純粹的SQL解決方案,評分程序獨立於應用程序 - 因此它更具可移植性。 – MaxPowers 2013-05-10 17:27:01

+0

同樣,你可以說這個SQL代碼是非常令人興奮的,將邏輯移動到應用程序將創建一個獨立於SQL引擎的解決方案......或者,簡而言之,它歸結爲:你需要這種獨立性? – 2013-05-10 22:35:23

回答

2

大部分這些文字應該是數據,而不是代碼。我強烈建議將這些巨型開關重構爲數據,以便更簡單的查詢可以對其進行評估。一個「純SQL」解決方案將更加可行,並且從長遠來看,性能和維護都會更好。也許Scoring表,你可以加入並比較?

Scoring (Question, Answer, Result)是一種概念上的可能性,希望不要過於簡單化。

正如人們所說的,"You can write FORTRAN in any language."

即使T-SQL,它似乎。

UPDATE

如果這些計算已經完成,您已在當前事務中更新的表,沒有必要簡單地重新做,因爲他們還沒有提交。如果事務中的更早更新,此事務中的任何查詢都將獲取此事務的更新數據。

更多關於Sybase ASE transactions

此外,你不應該指望GOwork in a stored procedure。它在IDE中用作批處理分隔符,而不是事務控制。

+0

他們實際上正在將數據保存到計分表中 - 先前的查詢在前面的陳述中爲相同的子量表生成分數。也許我的愚蠢行爲是在同一筆交易中完成的 - 因爲在交易完成之前我無法選擇結果 - 這就是爲什麼我有冗餘。有沒有一種方法可以在您處於同一事務中時從尚未提交的事務中選擇一個值?否則,如果我使用單獨的事務並且出現錯誤,我可能會有孤兒值。 – MaxPowers 2013-05-10 17:52:25

+0

在我看來,你還是希望將所有這些「case」都表示爲表中的行。 – 2013-05-10 17:59:39

+0

當您處於交易中時,您在該交易中完成的所有先前更改都將顯示給您。 – 2013-05-10 18:01:24