#author("2024-10-05T22:20:31+09:00","default:admin","admin")
#author("2024-10-05T22:26:06+09:00","default:admin","admin")
#navi(../)
#Contents
------------------------
PostgreSQLで、メモリマスタテーブルとCPUマスタテーブルがそれぞれ異なる時間が歯抜けしている状況に対応するには、以下の手順でSQLクエリを構築します。~

**テーブル構成 [#n7a4bd96]
-時間マスタテーブル (time_master): 全ての時間が格納されている。
--time (時間)
-メモリマスタテーブル (memory_master): メモリ使用率を格納。
--pcname (PC名)
--day (日付)
--time (時間)
--used (使用率)
-CPUマスタテーブル (cpu_master): CPU使用率を格納。
--pcname (PC名)
--day (日付)
--time (時間)
--used (使用率)

**ステップ 1: すべての時間と pcname, day の組み合わせを生成 [#jee165e0]
まず、pcname と day のすべての組み合わせに対して、時間のリストを組み合わせるために、CROSS JOIN を利用します。

sql
 -- メモリマスターとCPUマスターのすべての `pcname` と `day` を統合
 WITH all_times AS (
     SELECT DISTINCT pcname, day FROM memory_master
     UNION
     SELECT DISTINCT pcname, day FROM cpu_master
 )
 -- すべての時間と組み合わせる
 SELECT a.pcname, a.day, t.time
 FROM all_times a
 CROSS JOIN time_master t;
**ステップ 2: メモリとCPUのデータを時間マスタと結合 [#l76815c8]
次に、上記の pcname, day, time の組み合わせに対して、memory_master と cpu_master のデータを LEFT JOIN して、それぞれの時間で使用率のデータを補完します。

sql
 WITH all_times AS (
     SELECT DISTINCT pcname, day FROM memory_master
     UNION
     SELECT DISTINCT pcname, day FROM cpu_master
 )
 -- すべての時間と組み合わせる
 SELECT a.pcname, a.day, t.time, m.used AS memory_used, c.used AS cpu_used
 FROM all_times a
 CROSS JOIN time_master t
 LEFT JOIN memory_master m ON a.pcname = m.pcname AND a.day = m.day AND t.time = m.time
 LEFT JOIN cpu_master c ON a.pcname = c.pcname AND a.day = c.day AND t.time = c.time;
このクエリにより、全ての pcname, day, time の組み合わせに対して、memory_master と cpu_master のデータを結合し、両テーブルで欠けている部分が NULL で表示されます。

**ステップ 3: 欠けているデータを確認 [#o4e9abe9]
memory_master または cpu_master のデータが欠けている場合、そのレコードの memory_used または cpu_used が NULL となります。これを確認するために、NULL の行だけをフィルタリングします。

sql
 WITH all_times AS (
     SELECT DISTINCT pcname, day FROM memory_master
     UNION
     SELECT DISTINCT pcname, day FROM cpu_master
 )
 -- 欠けているデータを確認
 SELECT a.pcname, a.day, t.time, m.used AS memory_used, c.used AS cpu_used
 FROM all_times a
 CROSS JOIN time_master t
 LEFT JOIN memory_master m ON a.pcname = m.pcname AND a.day = m.day AND t.time = m.time
 LEFT JOIN cpu_master c ON a.pcname = c.pcname AND a.day = c.day AND t.time = c.time
 WHERE m.used IS NULL OR c.used IS NULL;
**1分ごとにデータを整えるSQL文 [#rbe44024]
 WITH data_with_timestamp AS (
     SELECT 
         pcname,
         date || ' ' || time AS timestamp_str,  -- Combine date and time
         total,
         avail
     FROM your_table
 )
 SELECT DISTINCT ON (pcname, date_trunc('minute', to_timestamp(timestamp_str, 'YYYY/MM/DD HH24:MI:SS')))
     pcname,
     to_timestamp(timestamp_str, 'YYYY/MM/DD HH24:MI:SS') AS full_timestamp,
     total,
     avail
 FROM data_with_timestamp
 ORDER BY pcname, date_trunc('minute', to_timestamp(timestamp_str, 'YYYY/MM/DD HH24:MI:SS')), full_timestamp DESC;



**Aテーブルのpcnameを利用してBテーブルに対しインサートするPLSQL文 [#ocf2eb4f]
 DO $$
 DECLARE
     rec RECORD;
 BEGIN
     -- Loop through each unique pcname
     FOR rec IN 
         SELECT DISTINCT pcname FROM your_source_table
     LOOP
         -- Insert the latest data per minute for each pcname
         INSERT INTO your_target_table (pcname, date, time, total, avail)
         SELECT DISTINCT ON (pcname, date_trunc('minute', to_timestamp(date || ' ' || time, 'YYYY/MM/DD HH24:MI:SS')))
             pcname,
             date,
             time,
             total,
             avail
         FROM your_source_table
         WHERE pcname = rec.pcname  -- Filter by current pcname in the loop
         ORDER BY date_trunc('minute', to_timestamp(date || ' ' || time, 'YYYY/MM/DD HH24:MI:SS')), 
                  to_timestamp(date || ' ' || time, 'YYYY/MM/DD HH24:MI:SS') DESC;
     END LOOP;
 END $$;

**まとめ [#pfb90eff]
このクエリでは、memory_master と cpu_master のデータがそれぞれ欠けている時間を特定できます。また、memory_used や cpu_used が NULL の部分は、欠けているデータですので、補完や追加処理が可能です。

もしさらにデータを補完したい場合、デフォルト値を使用するか、追加データを挿入するロジックを実装することができます。
**情報ソース [#x6fcbc0f]
-[[ChatGPT>https://openai.com/ja-JP/chatgpt/]]

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS