見出し画像

データベース検索ができる簡易デスクトップアプリ作成【完成版】


設計図

前回投稿でwhile文を使用して、main()に記述した処理をループする方法について紹介しました。

基本はこの形で、main()の中身を中心に変えていきます。条件は以下の通りです。

  1. これまでの投稿で、JADERのデータベースを用いて医薬品名から検索するパターンと副作用から検索するパターンの2種類を作成したのでモード選択を追加

  2. モード選択時に指定した文字以外を入力してしまった時の処理を追加

  3. 医薬品にしても副作用にしても日本語入力をするので、条件分岐の際に全角入力も可能にする(「y」だけでなく「y」も可としたい)

完成イメージはこんな感じです。

モード選択

コードを見やすくするために、医薬品名からもしくは副作用から検索するコードをそれぞれsearchByDrugName()、searchBySideEffect()という関数で定義します。関数を実行した結果をresultsという変数に格納して返すようにしておきます。

def searchByDrugName():
    drug_name = input('一般名もしくは販売名>')
    db = sqlite3.connect('side_effects.db')
    c = db.cursor()
    c.execute("""
            SELECT `有害事象`, count()
            FROM (
                SELECT DISTINCT * FROM join_table 
                WHERE (`医薬品(一般名)` LIKE ? OR `医薬品(販売名)` LIKE ?) 
                AND 医薬品の関与 = '被疑薬'
                ) AS subquery
            GROUP BY `有害事象`
            ORDER BY count() DESC
            """, [f'%{drug_name}%', f'%{drug_name}%'])
    results = c.fetchall()
    c.close()
    db.close()
    return results
def searchBySideEffect():
    side_effect = input('有害事象を入力>')
    db = sqlite3.connect('side_effects.db')
    c = db.cursor()
    c.execute("""
            SELECT `医薬品(一般名)`, count()
            FROM (
                SELECT DISTINCT * FROM join_table 
                WHERE 有害事象 like ? 
                AND 医薬品の関与 = '被疑薬'
                ) AS subquery
            GROUP BY `医薬品(一般名)` 
            ORDER BY count() DESC
            """, 
            [f'%{side_effect}%'])
    results = c.fetchall()
    c.close()
    db.close()
    return results

モード選択は、if文で条件分岐を作ればできそうです。main()の中に条件分岐を作成し、「d」を選べば医薬品からの検索(searchByDrugName())を、「s」を選べば副作用からの検索(searchBySideEffect())を実行できるようにします。
続けて検索結果を表示するコードを記述します。該当データがなかった場合は、その旨を表示するようにlen(results)で条件分岐を使用します。

def main():
    selection = input('モード選択(医薬品名: d / 有害事象: s)>')
        if selection == 'd':
            results = searchByDrugName()
        elif selection == 's':
            results = searchBySideEffect()

        if len(results) == 0:
            print('■有害事象の報告はありません。  \n')
        else:
            print('■有害事象の報告内容は以下の通りです。')
            for result in results:
                print(f'・{result[0]}: {result[1]}件')
            print('')


指定した文字以外を入力した場合の対処

モード選択で「d」もしくは「s」以外が入力されてしまったら処理が終了してしまいます。終了させないようwhileループを作成しましょう。
逆に、ちゃんと「d」または「s」が入力され、resultsが返ってきたときはループを終了し先に進めるように「break」を入れておきます。
main()を修正します。

def main():
    while True:
        selection = input('モード選択(医薬品名: d / 有害事象: s)>')
        if selection in ['d', 's']:
            if selection == 'd':
                results = searchByDrugName()
            elif selection == 's':
                results = searchBySideEffect()

            if len(results) == 0:
                print('■有害事象の報告はありません。  \n')
                break
            else:
                print('■有害事象の報告内容は以下の通りです。')
                for result in results:
                    print(f'・{result[0]}: {result[1]}件')
                print('')
                break
        else:
            print('***入力が正しくありません***  \n')

最初のifで「d」あるいは「s」かそれ以外を判定します。リストに格納し、リストに含まれるかどうかを判定するような書き方になっています。
リストに入っていない文字が入力されると、elseで規定した処理が実行され「***入力が正しくありません***」と表示されます。ここにはbreakを入れていないので、while Trueの無限ループは続き、モード選択に戻ることになります。

全角文字にも対応した条件分岐

モード選択にしても終了するかどうかの条件分岐にしても、日本語入力(全角文字)での入力に対応していると全角半角の切り替えを挟む必要がなくなるので便利です。
上記で行ったように、リストの中に許容する文字を入れておけば良いのでmain()は最終的にこんな感じになりました。

def main():
    drugs = ['d', 'd']
    sideeffects = ['s', 's']
    while True:
        selection = input('モード選択(医薬品名: d / 有害事象: s)>')
        if selection in drugs + sideeffects:
            if selection in drugs:
                results = searchByDrugName()
            else:
                results = searchBySideEffect()
            if len(results) == 0:
                print('■有害事象の報告はありません。  \n')
                break
            else:
                print('■有害事象の報告内容は以下の通りです。')
                for result in results:
                    print(f'・{result[0]}: {result[1]}件')
                print('')
                break
        else:
            print('***入力が正しくありません***  \n')

全コード

最後にmain()の実行をwhile Trueでループにすれば完成です。

import sqlite3
import pandas as pd

def searchByDrugName():
    drug_name = input('一般名もしくは販売名>')
    db = sqlite3.connect('side_effects.db')
    c = db.cursor()
    c.execute("""
            SELECT `有害事象`, count()
            FROM (
                SELECT DISTINCT * FROM join_table 
                WHERE (`医薬品(一般名)` LIKE ? OR `医薬品(販売名)` LIKE ?) 
                AND 医薬品の関与 = '被疑薬'
                ) AS subquery
            GROUP BY `有害事象`
            ORDER BY count() DESC
            """, [f'%{drug_name}%', f'%{drug_name}%'])
    results = c.fetchall()
    c.close()
    db.close()
    return results
    
def searchBySideEffect():
    side_effect = input('有害事象を入力>')
    db = sqlite3.connect('side_effects.db')
    c = db.cursor()
    c.execute("""
            SELECT `医薬品(一般名)`, count()
            FROM (
                SELECT DISTINCT * FROM join_table 
                WHERE 有害事象 like ? 
                AND 医薬品の関与 = '被疑薬'
                ) AS subquery
            GROUP BY `医薬品(一般名)` 
            ORDER BY count() DESC
            """, 
            [f'%{side_effect}%'])
    results = c.fetchall()
    c.close()
    db.close()
    return results

def main():
    drugs = ['d', 'd']
    sideeffects = ['s', 's']
    while True:
        selection = input('モード選択(医薬品名: d / 有害事象: s)>')
        if selection in drugs + sideeffects:
            if selection in drugs:
                results = searchByDrugName()
            else:
                results = searchBySideEffect()
            if len(results) == 0:
                print('■有害事象の報告はありません。  \n')
                break
            else:
                print('■有害事象の報告内容は以下の通りです。')
                for result in results:
                    print(f'・{result[0]}: {result[1]}件')
                print('')
                break
        else:
            print('***入力が正しくありません***  \n')

if __name__ == '__main__':
    while True:
        main()
        yes = ['y', 'Y', 'y', 'Y']
        choice = input('検索を終了しますか?(y/ )>')
        if choice in yes:
            break
        else:
            continue

これを「JADERsearch.py」という名前で保存し、batファイルで召喚すればデスクトップアプリとしていつでも簡単に使用できます!

cd C:\Users\...(ディレクトリパス)
py JADERsearch.py
好きな画像をアイコンにして普段使いに!

業務でデータベースを扱うことはしばしばあります。といっても、Accessを使ったことはあまりなかったのでExcelをデータベースとして使用していましたが、SQLite3を勉強し始めてからAccessの使い方も含めデータベースの扱いが分かってきた気がします。
データベースから何かを検索する場合でも、Excelの検索機能よりqueryを使用して検索し出力方法も加工できる方が断然見やすく使いやすいです。いろんなことに応用できそうですね。
ちなみに、これまでExcelに入力されていた問い合わせ記録をデータベース化し、Streamlitでwebアプリにしたところ利便性が爆上がりしました。スマホからも検索・閲覧できるのが便利です。
みなさんも埋もれている情報を普段使いにできるよう試してみてください!

いいなと思ったら応援しよう!