入院日の点滴量を調べるSQL(正規表現を使用)
脱水の多い季節です。
この仕事をしていると、夏と言えば脱水で救急医療加算を算定しようとなるのですが、さてEFファイルから対象患者を探すことは出来るでしょうか?
結論から言えば、出来るけど面倒です。
記録されている点滴の内容はこんな感じですね。
診療明細名称 | 行為回数 | 使用量 |
---|---|---|
ラクテック注 500mL | 1 | 3 |
嫌がらせのように全角文字で記録されているのがポイントです。まずこれを数値データにしてやらないといけません。
ステップとしては
全角英数字を半角英数字にする
mlという文字の直前にある数字のみを抽出する
2で得られた数字に行為回数と使用量をかけて合計する
さて、この中で一番困難なのは2番です。
単純なテキスト処理では用を成しません。とうとう、正規表現を使うときがやってきました。
正規表現とは
残念ながら正規表現の説明を出来るほど私は詳しくありませんので、サルでもわかる正規表現さんをどうぞ。たぶん一番わかりやすい説明がされたサイトさんです。
では早速SQLを書いてみます。
WITH eng AS (select データ識別番号,入院年月日,実施年月日,病棟コード,診療明細名称,行為回数,使用量,translate(診療明細名称, '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrsuvwxyz' , '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz') AS 診療明細名称2 from ef1607 where データ区分 = 33 AND 入院年月日 = 実施年月日) select 病棟コード,データ識別番号-10 AS ID,実施年月日,SUM(CAST(substring(診療明細名称2 from '([0-9]*)mL') as Numeric)*行為回数*使用量) from eng Where 診療明細名称2 ~ '[0-9]*mL' AND 診療明細名称2 !~ '\DmL' group by 病棟コード,データ識別番号,実施年月日
まず最初のWITH句で全角英数字を変換しています。これにはtranslate
関数を使います。
続いてSUM(CAST(substring(診療明細名称2 from '([0-9]*)mL') as Numeric)*行為回数*使用量)
という見るもおぞましい箇所が出てきますが、これがステップ2と3を行う部分です。
substring(診療明細名称2 from '([0-9]*)mL'
が正規表現を使用したテキスト処理です。
substing関数は、最初の引数で指定したレコードから、from 'なんとか'で指定したパターンに従い文字列を抽出する関数になります。では、肝心の正規表現部分を説明しましょう。
[0-9]が任意の数字を表し、はそれが任意の回数繰り返される、という意味です。
合わせて[0-9]とすることで、「何か数字が入っている部分を抜き出す」効果が得られます。
[0-9]*mL
とすれば、500mLが抜き出されます。
しかし今回抜き出したいのは数字だけですので、その部分を()で囲んでいます。
これで数字データが得られた・・・と思いきや、ここで得られるのは文字列ですので、CAST
で数字型に変換し、更にそれをSUM
で合計します。我ながらひどいSQL文ですね。
ふう。どうにか点滴の使用量を抽出することが出来ました。
と思いきや、実はEFデータには「そもそもmL単位が入っていない(留置針など)」、「50mg/mL」のように点滴量とは関係ない形でmLが入っているデータが混在しています。
仕方がないのでWhere 診療明細名称2 ~ '[0-9]*mL'
AND 診療明細名称2 !~ '\DmL'
でそれらは除外しました。
診療明細名称2 ~ '[0-9]*mL'
は奇妙に見えるかも知れません。~
はLIKE文の正規表現版です。
LIKE文のように、特定のパターンにマッチしたデータを指定することが出来ます。
!~
はNOT LIKE
と同じ働きをします。\D
は「数字以外」を意味しますので、この2行で「○○○mLという表記があり、かつmLの直前が数字であるもの」のみを抽出することになります。
やれやれ。酷い目に遭いました。
しかし、正規表現は極めて強力な手段です。
コードが呪文めいて見えてしまい、後で修正するとき酷く苦労しそうですが、慎重に使えば大きな助けになるでしょう。