1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LLMへのプロンプト例。SQLクエリ編

Posted at

はじめに

LLMへのプロンプト例、とくに「SQLクエリの作成をさせたもの」を忘備録として挙げておきます。

LLMにある程度しっかり(適当すぎるとダメだけど、完璧じゃなくてもなんとかなる)プロンプトを書くと、わりとそのまま使えるようなコードを書いてくれます。そのまま使えなくとも手直ししたら十分なものになります。一から自分で書くよりも速いですし、プロンプトを書くことを通して自分のなかでも整理されます。あえて複数パターンかかせて、違いやメリットデメリットをきくと勉強にもなります。

例文

投稿用に、元々のプロンプトを一般的な内容になるようにLLMに書き替えさせたうえで掲載しています。

・ストアドの作成1

以下の要件を満たすストアドプロシージャ「SP_CalcMonthlyReport」を作成したい。
概要:テーブル「WorkLog」(作業ログ)のデータをもとに、テーブル「MonthlyReport」(月次レポート)を更新・挿入する。

■ 使用テーブル・カラム
1. WorkLog テーブル
   - EmpId       CHAR(8)    -- 社員(利用者)ID
   - LogDate     DATE       -- 作業日
   - Minutes     INT        -- 作業時間(分単位)

2. MonthlyReport テーブル
   - EmpId       CHAR(8)    -- 社員(利用者)ID
   - YearMonth   VARCHAR(7) -- 対象年月(YYYY-MM)
   - TotalMin    INT        -- 月間合計作業時間(分)

■ ストアド引数
   - @EmpId     CHAR(8)
   - @YearMonth VARCHAR(7)

■ 処理内容
1. 引数の @EmpId、@YearMonth に合致する WorkLog の行を抽出。該当データがなければ終了。  
2. 抽出した行の Minutes を合計し、MonthlyReport の TotalMin に設定。  
   - 該当レコードが存在しない場合は INSERT  
   - 既存レコードがある場合は UPDATE
返答例

CREATE PROCEDURE dbo.SP_CalcMonthlyReport
    @EmpId     CHAR(8),
    @YearMonth VARCHAR(7)  -- フォーマット: 'YYYY-MM'
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @TotalMin INT;

    -- 1. 指定社員・年月の WorkLog を集計
    SELECT @TotalMin = SUM(Minutes)
    FROM dbo.WorkLog
    WHERE EmpId = @EmpId
      AND CONVERT(CHAR(7), LogDate, 120) = @YearMonth;

    -- 該当データなしなら終了
    IF @TotalMin IS NULL
        RETURN;

    -- 2. MonthlyReport に既存レコードがあるか判定
    IF EXISTS (
        SELECT 1
        FROM dbo.MonthlyReport
        WHERE EmpId     = @EmpId
          AND YearMonth = @YearMonth
    )
    BEGIN
        -- 既存レコードなら UPDATE
        UPDATE dbo.MonthlyReport
        SET TotalMin = @TotalMin
        WHERE EmpId     = @EmpId
          AND YearMonth = @YearMonth;
    END
    ELSE
    BEGIN
        -- レコード不存在なら INSERT
        INSERT INTO dbo.MonthlyReport (EmpId, YearMonth, TotalMin)
        VALUES (@EmpId, @YearMonth, @TotalMin);
    END
END
GO

・ストアドの作成2

以下の要件を満たすストアドプロシージャ「SP_UpdateWorkDuration」を作成したい。

■ 概要
「DailyWorkLog」テーブルに記録された「開始時刻」と「終了時刻」から、作業時間(分単位)を算出し、「作業時間」列に更新する。

■ 対象テーブル:DailyWorkLog
-EmpId     :CHAR(8)   --社員ID
-WorkDate   :DATE    --作業日
-StartTime  :CHAR(5)   --開始時刻(HH:mm形式)
-EndTime   :CHAR(5)  --終了時刻(HH:mm形式)
-DurationMin :INT    --作業時間(分)

■ ストアドの引数
- @EmpId     CHAR(8)
- @WorkDate  DATE

■ 処理内容
1. @EmpId および @WorkDate に一致する DailyWorkLog の行を1件取得。該当行がなければ処理終了。
2. 該当行の StartTime または EndTime のいずれかが NULL または空文字列であれば処理終了。
3. StartTime および EndTime を HH:mm 形式として TIME 型に変換し、差分(分)を計算。
4. 計算結果(分)を DurationMin に更新。

※ 開始時刻と終了時刻は文字列(CHAR(5), 'HH:mm')として管理されているため、適切なパース処理が必要。

返答例

CREATE PROCEDURE SP_UpdateWorkDuration
    @EmpId     CHAR(8),
    @WorkDate  DATE
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE 
        @sTime    CHAR(5),
        @eTime    CHAR(5),
        @tStart   TIME(0),
        @tEnd     TIME(0),
        @duration INT;

    -- 1. 対象行の取得
    SELECT 
        @sTime = StartTime,
        @eTime = EndTime
    FROM DailyWorkLog
    WHERE EmpId = @EmpId
      AND WorkDate = @WorkDate;

    -- 該当行なしなら終了
    IF @@ROWCOUNT = 0
        RETURN;

    -- 2. 時刻文字列の NULL または空文字チェック
    IF @sTime    IS NULL OR LTRIM(RTRIM(@sTime)) = ''
       OR @eTime IS NULL OR LTRIM(RTRIM(@eTime)) = ''
    BEGIN
        RETURN;
    END

    -- 3. 文字列 → TIME 型に変換(パース)し、例外時は終了
    BEGIN TRY
        SET @tStart = CONVERT(TIME(0), @sTime, 108);
        SET @tEnd   = CONVERT(TIME(0), @eTime,   108);
    END TRY
    BEGIN CATCH
        RETURN;
    END CATCH

    -- 差分(分単位)を計算
    SET @duration = DATEDIFF(MINUTE, @tStart, @tEnd);

    -- 4. 更新
    UPDATE DailyWorkLog
    SET DurationMin = @duration
    WHERE EmpId    = @EmpId
      AND WorkDate = @WorkDate;
END
GO


・テーブル値関数の作成

以下の要件を満たすテーブル値関数「UF_GetWorkdaysOfMonth」を作成したい。

■ 概要  
指定された年月(例: '2025-07')に存在するすべての日付を列挙し、各日付が「平日か休日か」を示す情報を付加して返す。

■ 引数  
- @YearMonth  VARCHAR(7)  
  ※ 形式は 'YYYY-MM'
  
■ 返却されるテーブル構成(戻り値)
- WorkDate      DATE     --対象年月に含まれる日付       
- IsWorkday     CHAR(1)  --平日なら '1'、休日なら '0'   

■ 判定仕様  
- 土曜日・日曜日を「休日」とし、それ以外を「平日」とみなす  
- 祝日等の判定は含めない(必要に応じて別テーブルで拡張可能)

■ 例:`SELECT * FROM UF_GetWorkdaysOfMonth('2025-07')`  
→ 2025年7月1日~31日の各日について、曜日に応じたフラグが表示される

返答例

CREATE FUNCTION UF_GetWorkdaysOfMonth
(
    @YearMonth VARCHAR(7)  -- 例: '2025-07'
)
RETURNS TABLE
AS
RETURN
WITH DateRange AS (
    -- 開始日と終了日を計算(1日~末日)
    SELECT
        CAST(@YearMonth + '-01' AS DATE) AS StartDate,
        EOMONTH(CAST(@YearMonth + '-01' AS DATE)) AS EndDate
),
Numbers AS (
    -- 最大31日分の数列(0~30)を生成
    SELECT TOP 31 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 AS n
    FROM master.dbo.spt_values
),
AllDates AS (
    -- 開始日 + n日 を加算して当月の日付を生成
    SELECT DATEADD(DAY, n, StartDate) AS WorkDate
    FROM DateRange
    CROSS JOIN Numbers
    WHERE DATEADD(DAY, n, StartDate) <= EndDate
)
-- 曜日判定(土日を休日、それ以外を平日)
SELECT
    WorkDate,
    CASE 
        WHEN DATEPART(WEEKDAY, WorkDate) IN (1, 7) THEN '0'  -- 日曜=1, 土曜=7(SET DATEFIRST の既定値に依存)
        ELSE '1'
    END AS IsWorkday
FROM AllDates

・テーブル値関数の修正

以下の要件を満たすテーブル値関数「UF_GetWorkdaysByCutoff」を作成・修正したい。

■ 概要  
指定された任意の日付(@TargetDate)をもとに、締め日基準の1か月間の出勤対象日(勤務日)を返す。
この関数は、もともと「月初〜月末」の範囲を対象としていた「UF_GetWorkdaysOfMonth」関数の代替として利用する。

■ 主な修正点
引数の変更
- 【旧】@YearMonth  (VARCHAR(7))  
- 【新】@TargetDate (DATE)  
  → 指定された日付をもとに、締め日ロジックで判断する。

締め日による判定
- 締め日は別テーブル「Config_WorkSettings」の「CutoffDay」列から取得する。  
  - WHERE 設定種別 = 'CUTOFF_DAY'
  - CutoffDay は 1~31 の整数で格納されている

- 指定された @TargetDate が「締め日より後」の場合 → 当月扱い  
- 締め日以前(含む)の場合 → 前月扱い

対象期間の例(例:締め日=20)
 指定日      対象期間              
 2025-07-10 2025/06/21~2025/07/20 
 2025-07-25 2025/07/21~2025/08/20 


■ 返却されるテーブル構成
WorkDate     DATE     該当期間に含まれる日付       
IsWorkday    CHAR(1)  平日なら '1'、休日なら '0'   

※ 土日を休日とし、平日のみを '1' とする(祝日除外)

返答例

CREATE FUNCTION UF_GetWorkdaysByCutoff
(
    @TargetDate DATE  -- 例: '2025-07-10'
)
RETURNS TABLE
AS
RETURN
WITH Cutoff AS (
    -- 締め日(1~31)を取得
    SELECT CAST(CutoffDay AS INT) AS CutoffDay
    FROM Config_WorkSettings
    WHERE 設定種別 = 'CUTOFF_DAY'
),
RangeBase AS (
    SELECT 
        C.CutoffDay,
        -- ターゲット日の日付成分
        DAY(@TargetDate) AS TargetDay,
        -- ターゲット日の月初・前月・翌月補助
        EOMONTH(@TargetDate) AS ThisMonthEnd,
        EOMONTH(DATEADD(MONTH, -1, @TargetDate)) AS PrevMonthEnd
    FROM Cutoff C
),
Period AS (
    SELECT 
        -- 期間開始日と終了日を算出
        CASE 
            WHEN TargetDay > CutoffDay THEN DATEFROMPARTS(YEAR(@TargetDate), MONTH(@TargetDate), CutoffDay + 1)
            ELSE DATEFROMPARTS(YEAR(DATEADD(MONTH, -1, @TargetDate)), MONTH(DATEADD(MONTH, -1, @TargetDate)), CutoffDay + 1)
        END AS StartDate,
        CASE 
            WHEN TargetDay > CutoffDay THEN DATEFROMPARTS(YEAR(DATEADD(MONTH, 1, @TargetDate)), MONTH(DATEADD(MONTH, 1, @TargetDate)), CutoffDay)
            ELSE DATEFROMPARTS(YEAR(@TargetDate), MONTH(@TargetDate), CutoffDay)
        END AS EndDate
    FROM RangeBase
),
Tally AS (
    -- 最大日数用の連番(0〜62日分)
    SELECT TOP 62 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 AS n
    FROM master.dbo.spt_values
),
Dates AS (
    SELECT DATEADD(DAY, n, P.StartDate) AS WorkDate
    FROM Tally
    CROSS JOIN Period P
    WHERE DATEADD(DAY, n, P.StartDate) <= P.EndDate
)
SELECT
    WorkDate,
    CASE 
        WHEN DATEPART(WEEKDAY, WorkDate) IN (1, 7) THEN '0'  -- 日曜:1, 土曜:7(デフォルト設定)
        ELSE '1'
    END AS IsWorkday
FROM Dates;





・スカラー値関数

以下の要件を満たすスカラー値関数「UF_GetAssignedBranch」を作成したい。

■ 概要  
指定された従業員IDから、対応する所属拠点番号(BranchNo)を取得して返す。

■ 引数  
- @EmpCode  CHAR(4)  
  → 従業員IDを表す

■ 対象テーブル:EmployeeMaster
- EmpCode     CHAR(4)      --従業員ID               
- BranchNo    DECIMAL(3,0) --所属拠点番号           

■ 処理内容  
EmployeeMaster テーブルから、EmpCode が引数と一致する行を検索し、該当する BranchNo を返却する。

■ 注意点  
- 該当する従業員が存在しない場合は `NULL` を返す。

返答例

CREATE FUNCTION UF_GetAssignedBranch
(
    @EmpCode CHAR(4)
)
RETURNS DECIMAL(3, 0)
AS
BEGIN
    DECLARE @BranchNo DECIMAL(3, 0);

    SELECT @BranchNo = BranchNo
    FROM EmployeeMaster
    WHERE EmpCode = @EmpCode;

    RETURN @BranchNo;
END


おわりに

微妙だなってこともあれば、そう書いたらいいのか!ってこともあります。
効率的になっているし、学びもあるとも思うけれども、「一から自分で書く力」 については落ちてきているかもしれません。出来上がったコードをしっかり理解することは怠らないようにしたいです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?