OmniAICreator/Qiita-1.07M huggingface dataset:
SQLパズル　p57 14 電話とFAX　その２

# 概要
SQLパズル　p57 14 電話とFAX　その２の解法メモです。
題材は外部結合（OUTER JOIN）を使った行→列変換です。

# 要件

・分類のカラムが有り、値にはhomかfaxの２つの値を取る
・番号のカラムが有り、値には番号が入る。分類のカラムがhomなら電話番号、faxならfaxの番号

実現したいこととは、１つのレコードに家の電話番号とfax番号を表示させるようにしたい。
3列目が電話番号、４列目がfax番号

（行→列変換）


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/9fffbcd8-04ad-49bf-4c37-7905fe126339.png)

# SQL

## DDL
```sql
drop Table if exists personnel cascade;

CREATE table personnel
(emp_id integer primary key,
first_name char(20) not null,
last_name char(20) not null
);
drop table if exists phones cascade;
create table phones
(emp_id integer not null,
phone_type char(3) not null check(phone_type IN('hom','fax')),
phone_nbr char(12) not null,
primary key(emp_id,phone_type)
)
;
INSERT INTO Personnel VALUES(1, '山田', '太郎');
INSERT INTO Personnel VALUES(2, '上野', '二郎');
INSERT INTO Personnel VALUES(3, '高田', '三郎');
INSERT INTO Personnel VALUES(4, '松岡', '四郎');

INSERT INTO Phones VALUES(1, 'hom', 1111);
INSERT INTO Phones VALUES(1, 'fax', 2222);
INSERT INTO Phones VALUES(2, 'hom', 3333);
INSERT INTO Phones VALUES(3, 'fax', 4444);

```



## 答えのSQL
```sql
-- 答え
SELECT E1.last_name,E1.first_name,H1.phone_nbr AS Home,
       F1.phone_nbr AS FAX
    FROM (Personnel AS E1 LEFT OUTER JOIN Phones AS H1 -- 結合１回目
           ON E1.emp_id = H1.emp_id
           AND H1.phone_type = 'hom'
         )
         LEFT OUTER JOIN Phones AS F1	-- 結合２回目
           ON E1.emp_id = F1.emp_id
           AND F1.phone_type = 'fax'
;


-- 結合１回目
SELECT *
    FROM (Personnel AS E1 LEFT OUTER JOIN Phones AS H1
           ON E1.emp_id = H1.emp_id
           AND H1.phone_type = 'hom'
         )
;
-- 結合２回目
SELECT *
    FROM (Personnel AS E1 LEFT OUTER JOIN Phones AS H1
           ON E1.emp_id = H1.emp_id
           AND H1.phone_type = 'hom'
         )
         LEFT OUTER JOIN Phones AS F1
           ON E1.emp_id = F1.emp_id
           AND F1.phone_type = 'fax'
;
```

### 結合を分けてレコードの動きを確認
割とわかりやすいすね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/283f7244-034d-1538-80b3-d079568a38ab.png)


# 一言
行列変換の問題多いですね。
実装方法も数通りあるので、どちらで実装したほうが良いか見極めできるようになりたいですね。



# 参考

SQLパズル　p57 14 電話とFAX

SQLパズル　サポートページ
https://mickindex.sakura.ne.jp/database/db_support_sqlpuzzle.html#LocalLink-p14

達人に学ぶSQL徹底指南書第２版p157 外部結合で行列変換（行→列）
達人に学ぶSQL徹底指南書第２版p176 参考問題

github メモ
https://github.com/RYA234/SQL_Puzzle_Learning/commit/b0418d0d6e4562bf2cf9c915c6e746d7544cc7bf
【Youtube Data API】登録者が少ないVtuber検索

【目的】：登録者数が少ないVtuberの配信を検索する
【利用】：YouTube Data API v3

Youtube Data APIの使い方は他記事をご参照ください。

【参考にした記事】
　https://qiita.com/k8uwall/items/b3a2c09d15f827fe888e
　https://qiita.com/Charlesmiwakuno/items/78caaaf5b83559843d44

【実装コード】
```python
from apiclient.discovery import build

YOUTUBE_API_KEY = 'ここに取得したAPIキー' #APIキー
CHANNEL_MIN = 0           #チャンネル登録者数下限
CHANNEL_MAX = 1000        #チャンネル登録者数上限
QUERY = "歌枠 and Vtuber" #検索キーワード

youtube = build('youtube', 'v3', developerKey=YOUTUBE_API_KEY)

def get_video_info(part, q, order, type, eventType, maxResults):
    search_response = youtube.search().list(part=part, q=q, order=order, type=type, eventType=eventType, maxResults=maxResults).execute()

    return search_response['items']

def youtube_channel_detail(channel_id):
    search_response = youtube.channels().list(
        part='snippet,statistics',
        id=channel_id,
    ).execute()

    return search_response['items'][0]

if __name__ == '__main__':
    
    video_out = get_video_info(part='snippet',q=QUERY,order='date',type='video', eventType='live',maxResults=50)

    
    for item in video_out:
        video_id = item['id']['videoId']
        channel_id = item['snippet']['channelId']
        details = youtube_channel_detail(channel_id)
        if len(details) == 0:
            continue
        
        title = details['snippet']['title']
        count = details['statistics']['subscriberCount']
        
        if CHANNEL_MIN < int(count) < CHANNEL_MAX:
            print("タイトル：" + title)
            print("チャンネル登録者数：" + count)
            print("https://www.youtube.com/watch?v=" + video_id)
    
```

【実行結果（例）】
```
タイトル：＜チャンネル名１＞
チャンネル登録者数：331
https://www.youtube.com/watch?v=aaaaaaaaaaaa
タイトル：＜チャンネル名２＞
チャンネル登録者数：283
https://www.youtube.com/watch?v=iiiiiiiiiiii
```

【コード解説】
　キーワードで生配信を検索して、チャンネル登録者数で絞って表示する仕組み

【感想】
　Youtube Data APIは無料だが、APIを利用するためにGoogle Cloudに登録する必要があり、そのGoogle Cloudが有料だった。現在(2024年11月13日時点)では、Google Cloudが無料で試用できる期間があったため、無料で実験をした。

　APIを利用したクエリの発行には上限があり、そこまで何回も実行することはできなそうである。

　実験結果としては、求めていたチャンネル登録者数が少ないVtuberを検索することができたので良し(*´ω｀)
ResourceBundleのキー存在チェック


## 例

実務では、プロパティファイルの読み込みとプロパティキーのキーチェックは、メソッド化して引数渡して汎用的に使えるようにしておいた方がよいと思います。

```java
import java.util.MissingResourceException;
import java.util.ResourceBundle;

public class Sample {
	
	private final String SEND_PORT = "send.port";
	
	public void testMethod() {
	
		String sendPort = "";
		ResourceBundle bundle;
		try {
		    ResourceBundle bundle = ResourceBundle.getBundle("config");
		} catch (MissingResourceException e) {
		    // プロパティファイルが無かった時にMissingResourceExceptionがスローされる
            // TODO:例外処理
		}

		// 方法１　containsKeyメソッドでチェック
		try {
			if (resourceBundle.containsKey(SEND_PORT) {
				sendPort = resourceBundle.getString(SEND_PORT);
			} else {
				// TODO:プロパティファイルにキーが無かった時の処理
			}
		    sendPort = resourceBundle.getString(SEND_PORT);
		} catch (MissingResourceException ex) {
		    // プロパティファイルにキーが無かった時にMissingResourceExceptionがスローされる
            // TODO:例外処理
		}

		// 方法２　例外をキャッチしてスロー
		try {
		    sendPort = resourceBundle.getString("send.port");
		} catch (MissingResourceException ex) {
		    // プロパティファイルにキーが無かった時にMissingResourceExceptionがスローされる
            // TODO:例外処理
		}
	}
}
```
【Next.js】Missing Suspense boundary with useSearchParams 解消法

## 解消法

`useSearchParams`が使用されているコンポーネントを以下のように`<Suspense>`で括ることでエラーが解消します。

```tsx
'use client'
 
import { useSearchParams } from 'next/navigation'
import { Suspense } from 'react'
 
function Search() {
  const searchParams = useSearchParams()
 
  return <input placeholder="Search..." />
}
 
export function Searchbar() {
  return (
    <Suspense>
      <Search />
    </Suspense>
  )
}

```

https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout

## 原因

ルートが静的にレンダリングされる場合に`useSearchParams`を呼び出すと、最も近い`Suspense`境界までがクライアント側でレンダリングされます。
そのため、`Suspense`で括らない場合にページ全体がクライアント側でレンダリングされるようになり、JavaScriptの読み込みが完了するまで空白のページが表示されてしまう可能性があります。
これを避けるため、静的レンダリングのルート内に`useSearchParams`が使用されていて`Suspense`で括られていないコンポーネントが存在する場合にタイトルのエラーが発生します。

https://nextjs.org/docs/app/api-reference/functions/use-search-params#static-rendering
Mockitoのspyを使って部分的にモック化

Mockitoの標準的な使用方法では既存のインスタンスのpublicメソッドを直接モックにすることはできません。もしそれが必要であれば、Mockitoのspyを使って部分的にモック化することが可能です。
## 例

```java
// モックを作成
MyClass mockInstance = Mockito.mock(MyClass.class);

// publicメソッドの動作を設定
Mockito.when(mockInstance.somePublicMethod()).thenReturn("Mocked Value");

// spyを使う場合
MyClass realInstance = new MyClass();
MyClass spyInstance = Mockito.spy(realInstance);

// publicメソッドをモックにする
Mockito.doReturn("Mocked Value").when(spyInstance).somePublicMethod();
```

spyを使用することで、元のインスタンスの振る舞いを一部のみモックに置き換えることができるため、柔軟に制御が可能です。ただし、spyは通常のモックと異なり、元のインスタンスのメソッドもデフォルトでは呼び出されるため、必要な部分だけをモックに切り替えることに注意が必要です。

設計段階で、別クラス化しておいたほうがテストコードが書きやすいと思います。
Gemini の Function calling を試す

Google AI Studio で Gemini の Function calling を試したので、簡単にまとめます。

# 概要

Function calling は、その名前から受ける印象とは異なり、Gemini が関数を直接呼び出す機能ではありません。Gemini は、事前に定義された呼び出し条件に基づき、プロンプトの内容を解析します。プロンプトが指定条件に合致した場合、Gemini は条件に合致する部分をプロンプトから引数として抽出し、関数呼び出し要求を JSON 形式で返します。JSON には、関数名と抽出された引数が含まれます。

つまり、Function calling はプロンプトの内容を解析し、特定の関数を実行するための要求を出力する機能です。実際の関数の呼び出しや実行は、Gemini の外側、例えばクライアント側のアプリケーションで行います。

フローの例を示します。アプリケーションが主体となって LLM を制御して、回答を生成します。

```mermaid
sequenceDiagram
    participant User as ユーザー
    participant Middleware as アプリケーション
    participant LLM as Gemini
    participant External System as 外部システム
    
    User->>Middleware: ユーザーの質問
    Middleware->>LLM: 関数呼び出し確認
    LLM->>Middleware: 関数呼び出し要求
    Middleware->>External System: 関数実行
    External System->>Middleware: 実行結果
    Middleware->>LLM: 結果を添えて生成を指示
    LLM->>User: 最終応答
```

この仕組みにはいくつかの利点があります。

* **柔軟な実装:** Gemini は関数の呼び出し自体を行わないため、関数の具体的な実装はクライアント側で自由に決定できます。例えば、ローカルの Python スクリプトを実行したり、外部 API を呼び出したり、データベースにクエリを送信したりすることが可能です。
* **セキュリティ:** Gemini が直接外部システムにアクセスする必要がないため、セキュリティリスクを低減できます。
* **保守性:** 関数の追加や変更はクライアント側で行うため、Gemini のモデル自体を更新する必要がなく、保守が容易になります。
* **拡張性:** 様々な種類の関数やツールと連携させることで、Gemini の機能を拡張できます。

# 使用手順

Google AI Studio での使用手順を説明します。

まず新規チャットを作成します。

System Instructions に以下を記入します。

```
Function calling の結果を JSON で返してください。
```

画面右側の Tools にある Function calling を有効にして、Edit functions をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32057/aa86e2fa-169e-d122-58aa-eec1c2c5b58f.png)

関数を定義する画面が現れます。Try an example をクリックして、提示された `getWeather` 関数を使用します。Save をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32057/1ff5a8c7-e2e5-a895-50d1-6a9345000b1a.png)

プロンプトに「東京の天気は？」と入力すれば、以下のような JSON が返されます。

```json
{
  "name": "getWeather",
  "args": {
    "city": "東京"
  }
}
```

このようなやり取りをスクリプトから行うことで、取得した JSON に基づいた処理を行うことができます。

## 引数の追加

日時を指定して天気を取得する場合、関数の定義画面を開いて `date` という Property（引数に相当）を追加します。

こうすることで、「明日の東京の天気は？」といった質問に対応できるようになります。

```json
{
  "name": "getWeather",
  "args": {
    "date": "明日",
    "city": "東京"
  }
}
```

# まとめ

Function calling は、Gemini と外部システムを連携させる強力な機能です。これにより Gemini は自然言語理解に集中しつつ、必要に応じてタスクを外部システムに委譲することで、拡張性や専門性を向上させることができます。

また、Function calling はプロンプトの内容を解析するための手段としても利用できます。例えば地名の詳細を取得するための関数を登録することで、プロンプトに含まれる地名を抽出することができます。

# 関連記事

https://qiita.com/7shi/items/e27866ce51c6b9a0f605
Cloudflare Pagesのすすめ

こんにちは。

テックリードのTerukiです。

今回は先週紹介した[HonoXの記事](https://qiita.com/omt_teruki/items/2ac8911c42a973e2a1f2)で出てきたCloudflare Pagesについて書きます。

# Cloudflare Pages
https://www.cloudflare.com/ja-jp/developer-platform/products/pages/

引用：
>Pagesを使用すると、信頼できるフルスタックアプリケーションをわずかな時間で構築、デプロイ、配信できます。最低限の設定で、開発者、デザイナー、製品がコラボし、デプロイできます。

あんまりピンとこないですが、私は静的サイトを非常にシームレスに開発・デプロイを行える便利なやつというイメージでいます。

# LP開発で便利
みなさんは社内やクライアントからLPを作ってほしいと言われたらどのように開発しますか？

ローカルでHTMLやJavaScriptを書いている人もいれば、[前回の記事](https://qiita.com/omt_teruki/items/2ac8911c42a973e2a1f2)で使用したHonoXやAstroなど、[SSG](https://www.cloudflare.com/ja-jp/learning/performance/static-site-generator/)ができるフレームワークを使って生HTMLやJavaScriptを出力している人もいるかなと思います。

開発が終わった後の成果物はどのように本番環境に載せますか？
レガシーなやり方ではレンタルサーバを借りてFTPでアップロードしたり、zipにしてファイル共有サービスで納品したりしている方もいれば、CI/CDパイプラインを構築して自動で本番リリースなど作り込んでいる人もいるでしょう。

ローカル開発や本番リリースは一旦置いておいて、途中経過を社内やクライアントに見せる時はどうしていますか？
シチュエーションとしては結構あるかなと思いますが、出力したファイルをレンタルサーバの確認用フォルダにアップロードしてURLを渡したり、ngrokのようなトンネリングサービスを使ってそのURLを渡したりなどありますが結構面倒ですよね。
前者はシンプルにアップロード作業が面倒、後者はPCがオンラインでないと見られないなどありますね。

私は上記の2つとも過去にやったことがありますが、面倒が故に確認を少なくして手戻りが発生などありました。。

そこで便利なのがCloudflare PagesのプレビューURLです。

GitHub上でプルリクエストを作成すると下記のようにそのブランチのコミット時点での内容で実際に見られるURLを出力してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192685/dd29eff4-ec80-22ec-be99-bd559a35cd04.png)

これを社内やクライアントにそのまま送れば見てもらえば良いのでめちゃくちゃ便利。

面倒なアップロード作業もGitHubと繋がっているのでpushするだけですし、開発PCをオンラインにしておく必要もありません。

やり方はCloudflare Pagesで新規プロジェクトを立ち上げてGitHubのリポジトリと連携させるだけなので省略しますが、めちゃくちゃ簡単です。

# でも、お高いんでしょう？
ここまでめちゃくちゃ便利なのですが、小規模なアクセス数だったらフリープランで十分戦えます。（というかフリーランス時代のプロジェクトではそれで十分でした）

レンタルサーバならランニングコストがかかりますがCloudflareならタダです。
ランニングコストは顧客負担だったとしてもタダのほうがありがたいですね。

そもそもCloudflareはCDN屋なので万が一のスパイクアクセスも余裕で捌いてくれますしほとんど言う事無しです。

課金すれば画像最適化をしてくれるCloudflare Imagesや詳細なアナリティクス機能なども使えるのでもっと便利です。

デメリットを上げるとすれば初学者からは少々敷居が高いくらいでしょうか。
ただ、得られる恩恵が非常に大きいので多少勉強してでもやれるようになった方が絶対良いと私は思います。

※Cloudflareの回し者ではありません

# おわりに
ちょっと短いですがCloudflare Pagesは便利だぞという記事でした。

開発体験爆上がりなので社内やフリーランス案件で似たようなことをやっている方は触ってみると良いです。

Oh my teethでは当たり前のように使われています。今後も便利なサービスが出てきたら積極的に取り入れていきたいですね。


# Oh my teethについて
Oh my teethでは未来の歯科体験を創るために日々活動しています。

Techチームではより良いユーザー体験を提供するべく、Webフロントエンドからバックエンド、スマホアプリに機械学習モデルなど、さまざまなプロダクトを開発しています。

一緒に未来の歯科体験を創りませんか？興味がある方は是非こちらを確認してください。

https://oh.careers/

カジュアル面談も可能なので気軽に応募してみてください！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192685/0138b492-e02b-852e-61fa-fc065b53d285.png" width="450" />
開発についてのポエム

日常生活では計画とか立てないけど仕事では計画立てて進めることが一般的だから、思いつきでやるよりも計画を立てる方が優れているのかなと思う
でも普段から計画立てたくない

検索で出てくるQiitaの記事に助けられてます。いつもありがとう
kotlin - 関数の引数がラムダ式の場合のラムダ式の型の見方、関数の使い方

kotlinの関数の引数でラムダ式が使われているときの見方が、最初分からなかったので自分用にメモ( ..)φメモメモ

# 関数の表し方（前提知識的なの）
![2024-11-13_00h44_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2330584/286f03fd-ac3c-99d0-77f8-47416cfc2634.png)

# 関数の引数がラムダ式の場合（本題）

![2024-11-13_01h30_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2330584/f03dc9f2-97e7-d181-d592-423d2a163416.png)


# 関数の引数がラムダ式の場合の関数の使い方

![2024-11-13_01h49_28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2330584/c36eee42-804b-a022-6c9c-c005f20890c7.png)


このtest2()を使う時に、ラムダ式の引数<font color="Red">name: String</font>に値を入れたい場合


![2024-11-13_02h05_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2330584/9d985203-c10b-27a8-d02e-fbe476119327.png)


実際のサンプルコード↓

https://play.kotlinlang.org/#eyJ2ZXJzaW9uIjoiMi4wLjIxIiwicGxhdGZvcm0iOiJqYXZhIiwiYXJncyI6IiIsIm5vbmVNYXJrZXJzIjp0cnVlLCJ0aGVtZSI6ImlkZWEiLCJjb2RlIjoiZnVuIG1haW4oKSB7XG4gICAgdGVzdDIoXG4gICAgICAgIGxhbWJkYSA9IHt1c2VyTmFtZSAtPlxuICAgICAgICAgICAgdGVzdCh1c2VyTmFtZSlcbiAgICAgICAgfVxuICAgIClcbn1cblxuZnVuIHRlc3QobmFtZTogU3RyaW5nKTpCb29sZWFue1xuICAgIHByaW50bG4oXCJ0ZXN0KCnjgadwcmludDokbmFtZVwiKVxuICAgIHJldHVybiB0cnVlXG59XG5cbmZ1biB0ZXN0MihcbiAgICBsYW1iZGE6IChuYW1lOiBTdHJpbmcpIC0+IEJvb2xlYW4gPSB7ZmFsc2V9XG4pOlVuaXR7XG4gICAgbGFtYmRhKFwi55Sw5LitXCIpXG4gICAgcHJpbnRsbihcInRlc3QyKCnlrozkuoZcIilcbn0ifQ==


### メモ
メソッドの戻り値```Unit```は、空という意味（Javaの```void```と同じ）
BigQueryを無料で使うための環境構築

### 概要

今学習している技術書、「前処理大全」で解説されているBigQueryの環境を無料で使える
方法で構築しました

### BigQueryサンドボックスの構築手順

＊BigQueryサンドボックスとは
Google Cloud Platformが提供するBigQueryの試用オプション。
クレジットカード情報を入力することなくBigQueryを無料で利用できる

①以下のURLをブラウザで入力しBigQueryを開く
https://console.cloud.google.com/bigquery

②Googleアカウントで認証を行う。アカウントがない場合は新規作成。

③「プロジェクトを作成」を選択し任意のプロジェクト名をつけ
組織に所属しているアカウントの場合は組織の選択などを行う。

![スクリーンショット 2024-11-13 004855.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3926100/1d7955b2-7f28-e3a8-4635-efad6995a701.png)

④「作成」ボタンを押下するとサンドボックスを作成できる

![スクリーンショット 2024-11-13 005335.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3926100/aa63b056-493d-c5b3-b7c1-5af45ea1a1e8.png)
mysql.general_log2がINNODB_SYS_TABLESに存在するがTABLESに存在しない

TL;DR

RDSであれば、Troubleshootingをやめて、新規クラスターを作成しデータ移行するか、AWS Supportに連絡かをしましょう。

## 症状

MySQL8 にアップグレードする時、Precheckで下記のエラーが検知。文面通り、mysql.general_log2というTableがないのに、INNODB_SYS_TABLESに存在している。


```json
        {
            "id": "schemaInconsistencyCheck",
            "title": "Schema inconsistencies resulting from file removal or corruption",
            "status": "OK",
            "description": "Error: Following tables show signs that either table datadir directory or frm file was removed/corrupted. Please check server logs, examine datadir to detect the issue and fix it before upgrade",
            "detectedProblems": [
                {
                    "level": "Error",
                    "dbObject": "mysql.general_log2",
                    "description": "present in INFORMATION_SCHEMA's INNODB_SYS_TABLES table but missing from TABLES table"
                }
            ]
        }
```

クエリで取得した結果。

```sql
mysql> select * from information_schema.innodb_sys_tables where NAME = 'mysql/general_log2';
+----------+--------------------+------+--------+--------+-------------+------------+---------------+------------+
| TABLE_ID | NAME               | FLAG | N_COLS | SPACE  | FILE_FORMAT | ROW_FORMAT | ZIP_PAGE_SIZE | SPACE_TYPE |
+----------+--------------------+------+--------+--------+-------------+------------+---------------+------------+
|   124561 | mysql/general_log2 |    1 |      9 | 124547 | Antelope    | Compact    |             0 | Single     |
+----------+--------------------+------+--------+--------+-------------+------------+---------------+------------+
1 row in set (0.04 sec)

mysql> select table_name from information_schema.tables where TABLE_SCHEMA ='mysql' and TABLE_NAME = 'general_log2' ;
Empty set (0.02 sec)
````

## 原因

RDSのせいだと思われる。

ログをRotateする時に上手くいかず、ゴミが残ってた。

## 普通はどう対処する？

マスターユーザーで残っているファイルを削除。

```sql

mysql> select * from information_schema.innodb_sys_datafiles where path like "./mysql/general_log2.%";
+--------+--------------------------+
| SPACE  | PATH                     |
+--------+--------------------------+
| 124547 | ./mysql/general_log2.ibd |
+--------+--------------------------+
1 row in set (0.05 sec)
```

## RDSであれば打つ手がない

なぜなら、Master User(root)でもmysql Tableを変更する権限もないし、MySQLのファイルシステムにアクセスできないから。

## じゃどうすればいい

* データベースをDumpして新規クラスターに移行
* AWS Supportに連絡して対応してもらう
    * 解決できる保証がないけど
javascript 

学習備忘録
自力で作ると理解度UP

```aa.js
let maximum = parseInt(prompt('始めに0以外の数字を入力せよ'));
  while (isNaN(maximum) || maximum <= 0) {
    maximum = parseInt(prompt('有効な数字を入力せよ'));
  }

  const targetNum = Math.floor(Math.random() * maximum) +1;

  let answerNum = prompt('答えの数字を決めました。予想して0以外の数字を入力せよ');
  let count = 1;

    while (parseInt(answerNum) !== targetNum) {
      if (answerNum === 'q') break;

      if (isNaN(answerNum) || answerNum <= 0) {
        answerNum = prompt('0以外の有効な数字を入力せよ');
        continue;
      }
      count ++;
      if (answerNum > targetNum) {
        answerNum = prompt('数字が大きすぎます。再度入力せよ。');
      } else {
        answerNum = prompt('数字が小さすぎます。再度入力せよ。');
      }
    }
    if (answerNum === 'q') {
      alert('リタイアしました。また挑戦してください。');
    } else {
      alert(`正解！${count}回で当たりました。`);
    }
debianでコンソールのフォントを変更する

# はじめに
VMWareのVMや物理マシンのttyでフォントや文字サイズを変更する方法についてです。

# 注意
VMのttyのフォントが変更されるため、SSH接続などのptyのフォントは変更されません。
そちらは各々のターミナルソフトで調整してください。

# 対象OS
- Debian GNU/Linux
- その他Debian系Linux

# 方法① dpkg-reconfigureを使う
```shell
dpkg-reconfigure console-setup
```
encoding、charset、font、font sizeの順に対話的に聞かれるのでお好みのものを選択してください。

# 方法② 設定ファイルを編集する
```shell
vim /etc/default/console-setup
```
```shell:/etc/default/console-setup
# CONFIGURATION FILE FOR SETUPCON

# Consult the console-setup(5) manual page.

ACTIVE_CONSOLES="/dev/tty[1-6]"

CHARMAP="UTF-8"

CODESET="Lat15"
FONTFACE="TerminusBold"
FONTSIZE="11x22"

VIDEOMODE=

# The following is an example how to use a braille font
# FONT='lat9w-08.psf.gz brl-8x8.psf'
```
FONTFACE、FONTSIZEをお好みで変更してください。(上記のものは私が使用しているもの)

変更後、以下を実行。
```shell
systemctl restart console-setup.service
```
コピーコマンド

```:.batファイルのコード
@echo off

set local
rem 管理者実行
if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b)

powercfg -h off

REM バッチファイルのディレクトリパスを取得
set scriptDir=%~dp0

REM バックスラッシュを削除
set scriptDir=%scriptDir:~0,-1%


REM デバイス名を取得
set deviceName=★移行用PC_%COMPUTERNAME%

mkdir %scriptDir%\%deviceName%
set cpfolder=%scriptDir%\%deviceName%\dsp


rem メッセージを表示
echo:
echo フォルダを作成しました。Enterを押してください。
echo:
pause > NUL



rem デスクトップのフォルダパスを探す関数を定義 
set FolderPath= 
for %%F in (Desktop デスクトップ DESKTOP) do ( 
　　if exist "%UserProfile%\%%F" ( 
set FolderPath=%UserProfile%\%%F
 goto :found 
　　)
 )
 :found 
if defined FolderPath ( 
echo コピー中です。お手をふれない様にお願いします。
echo "完了"のメッセージが出るまでお待ちください。
 ) else ( 
echo 名前が違うようです…このバッチファイルの作成者に報告してください。
)




xcopy %FolderPath% %cpfolder% /E /V /H /R /Y /I /Q /C




rem メッセージを表示
echo:
echo デスクトップのコピーが完了しました。Enterを押してください。
echo:
pause > NUL


set cpfolderdcc=%scriptDir%\%deviceName%\DCCm

rem ドキュメントのフォルダパスを探す関数を定義 
set FolderPath= 
for %%F in (Document ドキュメント ﾄﾞｷｭﾒﾝﾄ DOCUMENT) do ( 
　　if exist "%UserProfile%\%%F" ( 
set FolderPath=%UserProfile%\%%F
 goto :found 
　　)
 )
 :found 
if defined FolderPath ( 
echo コピー中です。お手をふれない様にお願いします。
echo "完了"のメッセージが出るまでお待ちください。
 ) else ( 
echo 名前が違うようです…このバッチファイルの作成者に報告してください。
)


xcopy %FolderPath% %cpfolderdcc% /E /V /H /R /Y /I /Q /C




rem メッセージを表示
echo:
echo ドキュメントのコピーが完了しました。Enterを押してください。
echo:
pause > NUL



rem 画像フォルダーのコピー先フォルダを作成
set cpfolderPic=%scriptDir%\%deviceName%\pic

rem ピクチャーのフォルダパスを探す関数を定義 
set FolderPath= 
for %%F in (Picture ピクチャ ﾋﾟｸﾁｬ ピクチャー ﾋﾟｸﾁｬｰ 画像) do ( 
　　if exist "%UserProfile%\%%F" ( 
set FolderPath=%UserProfile%\%%F
 goto :found 
　　)
 )
 :found 
if defined FolderPath ( 
echo コピー中です。お手をふれない様にお願いします。
echo "完了"のメッセージが出るまでお待ちください。
 ) else ( 
echo 名前が違うようです…このバッチファイルの作成者に報告してください。
)


xcopy %FolderPath% %cpfolderPic% /E /V /H /R /Y /I /Q /C




rem メッセージを表示
echo:
echo すべてのコピーが完了しました。Enterを押してください。
echo:
pause > NUL

end local




```
ビットシフト演算子を理解する

# はじめに
使用するプログラムにおいて、ビットシフト演算子を使用する機会があったので、どのようなものなのか簡単にまとめたいと思います。

# 2進数と10進数
ビットシフト演算子を理解するためには、まず2進数と10進数について理解している必要があります。

2進数と10進数の対応表は以下のとおりです。
| 10進数 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 2進数 | 0 | 1 | 10 | 11 | 100 | 101 | 110 | 111 | 1000 | 1001 | 1010 |

### 2進数から10進数への変換方法
2の倍数に関する10進数と2進数の対応表は以下の通りです。2進数の桁が上がる時の10進数の値が記載されています。以下では、2進数を表現する時は一般的に8桁単位で表現するため、8桁未満の場合は頭に0をつけています。

| 10進数 | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 2進数 | 00000001 | 00000010 | 00000100 | 00001000 | 00010000 | 00100000 | 01000000 | 10000000 |

2進数から10進数への変換する場合は、2進数で1となっている10進数の値を合計することで10進数での値を求める事ができます。例えば、2進数の「00101010」を10進数に変換する場合、基準値が32、8、2の所でビットが1なので、2進数の「 00101010 」は10進数では「42」だと分かります。

上図を見ると、2進数において「1」の値を右に1ビットずらすと、10進数の値が2分の1になっていることが分かります。これが後述するビットシフトにつながります。

※ビットとは？
2進数における1桁のことを1ビット（bit）と言います。

## ビットシフト演算子
ビットシフト演算子 >> は、右ビットシフトを行う演算子です。これは、数値を2進数の形式で右にシフトさせる操作で、シフトさせた分だけ数値が小さくなります。

具体的な動作
- x >> n は、x のビット列を 右に n ビット だけシフトさせます
- これにより、数値は2のn乗で割った値に相当します（ただし、整数値で計算される）

### サンプルコード
```javascript: bitshift.js
let x = 16; // 16は2進数で 0001 0000
let result = x >> 2; // 右に2ビットシフト
console.log(result); // 出力は4（2進数では 0000 0100）
```
- 16 は2進数で 0001 0000 です
- これを 2 ビット右にシフトすると 0000 0100 になります
- 結果として 4 となります（16 ÷ 2^2 = 4）

# まとめ
ビットシフト演算子についてまとめました。

# Reference

https://www.infraexpert.com/study/ip1.html
cURLでGoogle Formsに回答してみる

# はじめに
できるという話を小耳にはさんで気になったのでやってみます。
# 適当なフォームを作る
設問1つだけの簡単なフォームを作りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3712912/08440bc3-ee75-6c8d-d425-244af15fe8bc.png)
# 必要な情報を取得する
各設問に対応するHTML要素のname属性を取得する必要があります。
フォーム回答画面のHTMLから探し出してもいいのですが、込み入っていて見つけるのが大変なので別の方法を提案します。

1. 回答画面にアクセスする
1. ディベロッパーツールのNetworkタブを開いておく
1. 適当な回答を入力して```送信```する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3712912/9e97bd80-2851-2d55-1820-1056b5b1e3e7.png)
1. Nameが```formResponse```のログを選択する
1. PayloadタブのFormDataを```view source```で見る

先頭にある```entry.```で始まる要素が入力データです。
今回の場合だと```entry.416791464=test+name```が取得できました。
```entry.416791464```がHTML要素のname属性、```test+name```が入力内容です。

回答が1つ作られてしまうので不要であれば削除します。
# URLを組み立てて送信する
フォームの送信先URLは```https://docs.google.com/forms/u/0/d/e/{フォームのID}/formResponse```です。
```{フォームのID}```は回答画面のURLに含まれているIDで、先ほど取得したネットワークログの```Request URL```からも確認できます。

これと回答内容を組み合わせてcURLで送信します。
回答内容は自由に書き換えることができます。
```bash
$ curl -X POST https://docs.google.com/forms/u/0/d/e/{フォームのID}/formResponse?entry.416791464=curl+test+name
```
フォームの管理画面？から回答を確認すると、送信した内容が確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3712912/00fa4371-3088-ef8f-df38-04b4c05c732a.png)
# おわりに
今回はcURLでGoogleFormsの回答をしてみました。
用途としてフォームの回答内容をスプレッドシートと紐づけて簡易的なデータベースとして使用できないかと考えましたが、取得するためにAPIを使う以外の方法を知らないので、結局APIを使うのならFormsを使う意味がないなーと…
いい方法があれば教えてください。
データ収集などには活用できそうですね。

最後までご覧いただきありがとうございました。
`useEffect` と `useLayoutEffect `の違いを理解する

## 概要
`useEffect`と`useLayoutEffect`の違いについて、混乱することが多かったのでまとめました。

## まとめ
早速ですが、違いは以下の通りです。

### 実行タイミング

`useEffect`と`useLayoutEffect`では、実行タイミングが異なります。

#### **useEffect**
  - **タイミング**: ブラウザの描画が完了した後に非同期的に実行されます
  - **特徴**: DOMの変更や、スタイルを動的に適用する場合、チラつきなどが発生する可能性がある

#### **useLayoutEffect**
  - **タイミング**: ブラウザが描画を行う前に同期的に実行されます
  - **特徴**: 同期的に実行されるため、パフォーマンスに影響を与える可能性があるが、チラつきが発生しない

### 主な使用ケース

#### **useEffect**
  - データfetch
  - 外部ライブラリとの連携

#### **useLayoutEffect**
  - DOMのサイズや位置の測定
  - スクロール位置の制御
  - 同期的なスタイル適用

## まとめ
以上です。
Reactのライフサイクルは混乱しがちなので、頭の片隅に入れておきます。
Railsでfile_fieldをいい感じに装飾する

[株式会社TECH LUCK](https://techluck.co.jp/?utm_source=qiita&utm_medium=article&utm_campaign=myarticle)という会社で代表兼エンジニアをしている齊藤です。

DXプロジェクト、開発プロジェクト、Rails開発などでお困りごとがありましたら[弊社HP](https://techluck.co.jp/?utm_source=qiita&utm_medium=article&utm_campaign=myarticle)からご相談をいただけますと幸いです。
以下のような問題に対応することが可能です。
- プロジェクトでRailsエンジニアが足りなくて困っている
- Railsのバージョンアップをしたいがノウハウ・リソースが足りなくて困っている
- オフショア開発をしているが、要件の齟齬やコード品質が悪いので改善したい

また、Railsエンジニアも募集しておりますので、興味がありましたら[弊社HP](https://techluck.co.jp/?utm_source=qiita&utm_medium=article&utm_campaign=myarticle)からご連絡いただけますと幸いです。

# 前提
毎回 `f.file_field` の装飾方法を調べているので、記事にして残しておきます。
実装を行うと以下のようなデザインになります。


**装飾がなにもない場合の f.file_field のデザイン**

![装飾なしのデザイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92443/c963ab33-ea17-ce58-8ecb-c470411c30a7.png)


**装飾後の f.file_field のデザイン**

装飾後のデザインになります。
"MVV.png" という文字はファイルを選択した後に、ファイル名がすぐにプレビューされるようにしたものになります。

![装飾後のデザイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92443/4e5f79eb-7e35-8e66-c35f-1dddfda23ab1.png)


# 実装内容

## HTMLファイル
erbファイルの内容

```erb:app/views/posts/new.html.erb
<%= form_with model: @post do |f| %>
  <%= f.label :image, '画像を選択する', class: 'file_field_design' %>
  <br>
  <%= f.file_field :image, class: 'form-control file_field_content' %>
  <div id="preview"></div>
<% end %>
```

## CSSファイル

CSSファイルの内容

```css:custom.css
input[type="file"] {
  display: none;
}

.file_field_design {
  padding: 5px 20px;
  color: #04B0FB;
  background-color: white;
  cursor: pointer;
  border-radius: 5px;
  border: 1px solid #04B0FB;
}
```

## JSファイル

JSファイルの内容。
file_fieldでファイルを選んだ際に、ファイル名がプレビューされるようになります。
DOMの操作などのために、jQueryをインストールしておく必要があるのでご注意ください。
違う

```js:app/javascript/application.js
import jquery from "jquery"
window.$ = jquery

$(document).ready(function() {
  function readFileName(input) {
    let files = input.files;

    if (files.length > 0) {
      $('#preview').html('');

      $.each(files, function(index, file){
        $('#preview').append(`<p>${file.name} </p>`);
      })
    }
  }

  let $fileField = $('.file_field_content');

  $($fileField).on('change', $fileField, function(){
    readFileName(this);
  });
});
```

以上となります。
MisskeyでCloudflare R2 Storageを使う方法

# 前提

Misskeyの構築済みで管理者権限を持っている

[cloudflare](https://dash.cloudflare.com/)のアカウントを持っている。

Cloudflareでドメインが使用できる状態。


## Cloudflareの設定

[Cloudflare Dashboard](https://dash.cloudflare.com/)を開きます。

左のバーのR2を押します。

右上にある Manage R2 API Tokens を押します。

Create API token を押します。

Permissions は Edit にします。

TTLは Custom となっているところを押して Forever にします

IP Filteringは空欄でおｋ もしかけたいのならIPを入力

大体画像のようになってたら Create API Token を押します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961201/1854a132-5246-b35c-ad16-80e76c0e74e4.png)


押すと Access Key ID と Secret Access Key が出てくるのでメモる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961201/809f4b94-7ee4-a7c7-5bae-23964fe3231a.png)


終わったら Finishを押して左上にあるR2を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961201/90f85053-0c3a-7d9c-0fdd-16ccd000d605.png)


次にCreate Bucket を押します。

Bucket name を決めて Create bucket

無事に終わると下のような画面になる

URLは使うのでメモる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961201/56024661-f937-3776-c79b-017f895e1c68.png)


Settingsのタブに行く。

Custom Domainsを追加する。

Connect Domainを押してファイル鯖のDomainとして使いたいドメインを入力してContinueを押してConnect domain

これでおｋ

## Misskeyの設定

次にMisskeyを開く。

コントロールパネルを押してオブジェクトストレージを押す

Base URL に https://さっき入力したドメイン

Bucket に さっき決めたBucket name

Prefix はそのまま

Endpoint にさっきメモしたURLを貼るが、.com以降はいらない。

Region はapac

Access key はさっきメモしたAccess keyを

Secret key はさっきメモしたSecret keyを

SSLを使用する はオンに

Proxyを利用する は任意 困ったらoffでおｋ

アップロード時に’public-read’を設定する は **必ずオンに**

s3ForcePathStyle はオンに

画像のようになっていることを確認して保存を押す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961201/6427fec8-3667-3cf1-8526-5bc84335a315.png)


終わったら適当な画像を上げてみて使えるか確認する

以上です。
Misskeyでjemallocを使う(Debian系統)

Misskeyでメモリアロケータをjemallocに変更する方法です

```bash
sudo apt install libjemalloc-dev libjemalloc2
```

でjemallocを入れて

```bash
sudo nano /etc/systemd/system/misskey.service
```

サービスのファイルを開いて

[Service]と[Install]の間に

```bash
Environment="LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2"
```

を入れる

```te
[Unit]
Description=Misskey daemon

[Service]
Type=simple
User=misskey
ExecStart=/usr/bin/npm start
WorkingDirectory=/home/misskey/misskey
Environment="NODE_ENV=production"
TimeoutSec=60
StandardOutput=journal
StandardError=journal
SyslogIdentifier=misskey
Restart=always
Environment="LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2" #新しく書いたの

[Install]
WantedBy=multi-user.target
```

こういうふうになる

保存して

```bash
sudo systemctl daemon-reload
sudo systemctl restart misskey
```

こうしてデーモンの再読み込みしてから再起動をすればできます
【Tableau】ドーナッツグラフの作成方法

Tableauでドーナッツグラフを描くには、
通常の円グラフの設定をいじるだけでは作成できません。
そのため、若干工夫が必要になります（イメージとしては大きさ違いの円グラフを２つ重ねるイメージ）。

### 手順
１． まずは通常の円グラフを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3437732/80c34ae3-9250-43f5-ac21-d0732a586d42.png)
２． 行に適当な計算式を追加する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3437732/7bc3c3de-03f1-fd17-50ee-4f387f56c70e.png)
３． 計算式を複製し、２重軸に設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3437732/b51e38cb-7936-69d9-307c-18cd64119932.png)
４． 追加した側の各設定を外す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3437732/f54931d8-a70f-5091-8fc7-6aee501d5f39.png)
５． 追加した側のサイズを変更することでドーナッツグラフの完成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3437732/dca11015-8310-7c16-bd75-5b4711613736.png)
６． あとは色や表示するラベルを編集し、軸のヘッダーやグラフの枠線・0ラインを削除すればきれいになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3437732/fb94977d-e9db-a869-bf08-3b4bc87833d4.png)

割合だけでなく、全体の合計値も一緒に表示できるため個人的には好きなグラフです。
Bun で @kubernetes/client-node を使用する際に UNABLE_TO_VERIFY_LEAF_SIGNATURE が発生する問題の解決法

Bunで@kubernetes/client-nodeを使用しようとすると下記のようなエラーが出る。(少なくとも私の環境では出た)

```console
Deployment failed ERR_TLS_CERT_ALTNAME_INVALID: ERR_TLS_CERT_ALTNAME_INVALID fetching "https://masternode:6443/api/v1/namespaces/default/configmaps". For more information, pass `verbose: true` in the second argument to fetch()
 path: "https://masternode:6443/api/v1/namespaces/default/configmaps"
```

これを解決するには、 

```js
NODE_TLS_REJECT_UNAUTHORIZED=0
```

という環境変数を設定してあげると正常に動作するようになった。

Bunは自己証明書周りの機能のバグがあるらしい？

https://github.com/oven-sh/bun/issues/10642

参考
https://github.com/oven-sh/bun/issues/4979#issuecomment-1715378319
ギャラリーで選択している項目の背景色を変える方法

ギャラリーで選択した項目の背景色を変えたい場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880604/80aac7a3-0dce-bb7a-5db4-ee677a653b65.png)

ギャラリーのFillプロパティの設定を変更したくなりますが、Fillプロパティはギャラリー全体の背景色なので、この場合は使用しません。
変更するのはギャラリーのTemplateFillプロパティです。

TemplateFillプロパティに以下の数式を記入します。
```javascript
If(ThisItem.IsSelected,RGBA(250,200,200,1),RGBA(0, 0, 0, 0))
```
ThisItem.IsSelectedはギャラリー内の項目を選択した際にtrueを返します。
If関数の第１引数に指定することで、選択した項目のみがtrueとなり、背景色が変わります。

ギャラリーを配置した際に、初期設定で表示されるRectangleも、VisibleプロパティにThisItem.IsSelectedが使用されています。
これだけでは選択した項目が分かりにくいので、背景色も変更すると親切だと思います。

ぜひお試しください。
タスクマネージャー100％ の状態で仕事してる人は、我に返りましょう

# 背景

会社で、全力で頑張ってる同僚がいる。
イケメンでノーマルなのに、私生活犠牲にしてるんじゃないかと思うほどに。
で、たまに熱出して休むこともあるけれど、在宅で頑張ろうとしちゃう。

こういう人に対して、

「メリハリ付けたほうがいいよ」

と言っても伝わらなかったので、ちょっと思いをまとめてみた

# タイトルについて

もうそのままです。

- タスクマネージャー 100% の PC で作業してて楽しいですか？

コンピューターの最適な負荷がどれくらいか？はよくわかりませんが、100% 近くで稼働してたらどうなるでしょう？

きっとそのうち壊れますよね。車で言うならエンジンブロー

人間だって同じです。

- 何のために仕事をするのか？
- 効率よく仕事をする為にはどうするか？


振り返る時間を持つことが大切

# 一つ目：最適な負荷と生産性

負荷が全くないのも、有り過ぎてもダメ。そう、僕の大好きな「バランスです」

ヤーキス・ドッドソンの法則では、

> 動機づけには、罰やストレスなどの不快なものが一定量あったほうが、効率が上昇する

と判明しています。

そう、負荷が低すぎても集中力が欠け、当然高すぎると過労で効率が低下します。適度が大切。

https://ja.wikipedia.org/wiki/%E3%83%A4%E3%83%BC%E3%82%AD%E3%83%BC%E3%82%BA%E3%83%BB%E3%83%89%E3%83%83%E3%83%88%E3%82%BD%E3%83%B3%E3%81%AE%E6%B3%95%E5%89%87

## 二つ目：タスクの取捨選択

世の中やらなくてもなんとでもなることが山ほどあるってことの理解が必要

転職したことある人ならわかると思いますが・・・

「この仕事、俺しか知らないから、俺がいなくなった後きっと困るだろうなぁ・・」

いざ転職してみると、９５％ぐらい、なんとかなります。（極稀に、連絡が来ますが :laughing: 


ってことで、大切なことはタスクを「見える化」して優先順位付け
例えば、毎朝「最優先」「通常」「低優先度」にタスクを分類し、その日のゴールを3つに絞って、それやったら帰る。

以下の本のタイトルのままですね

https://tower.jp/item/6000294?msockid=11842919a3186f073a8d3dfca2626eb6

## 三つ目：学びと生産性の向上

学び＝投資、をすることで、複利の効果を手に入れる

当然学びをする為には余裕も必要ですし、
そもそも仕事中に学ぶことだってできる筈

一つの方法として WOL: Working Out Loud があります
仕事の進捗や学びを共有し、チーム全体で成長するためのアプローチだそうです。

https://www.workingoutloud.com/about

例えば、チームで週次ミーティングや社内チャットツールを使って進捗や学びを共有することで、相互の理解が深まり、無駄な業務が減ります。互いに支援し合う Giver 文化になれば、自然と働きやすい環境が整います。

まぁ、普通に心理的安全性の高い、オープン思考な、アジャイル開発環境、ですよね？
アジャイルはいまやソフト開発だけではなく、組織にこそ当てはめるべきと言われてるわけで。

社内技術ブログだったり、社内SNS（Slack や Viva Engage など）で社内の繋がりを増やすことで、共創が進んでる会社も多いんじゃないんでしょうか？

こういったアウトプットで学びを定着させることは、随分昔にエドガー・デールという方が「ラーニングピラミッド（経験の円錐）」としてまとめています。
この理論によると、学んだ内容を他者に教える／すぐ使ってみると、最も高い学習定着率（約90％）が得られるとされています。

そう、技術ブログはまさにうってつけですよね :p

https://ja.wikipedia.org/wiki/%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%83%94%E3%83%A9%E3%83%9F%E3%83%83%E3%83%89


# なにより一番は、楽しむこと

まぁ、色々書いたけど、やっぱりこれですね

- 人生は一度きり、死ぬときに後悔しない生き方をするべきであり、どうしたらそうなれるかを、現時点で一番若い「今」考えて行動しましょう

好きなことを仕事にしちゃいけない、とかいう人もいますけど、「好きこそものの上手なれ」とも言いますし、好きで楽しんで仕事をすれば、定時内に遊びも入れて十分仕事こなせる筈です、きっと :laughing: 

で、家に帰ったら、可愛い子供と大好きな配偶者とイチャイチャして英気を養いましょう！
検索結果数を取得するPythonスクリプト



### **user**:

ChatGPT先生、教えてください。Google検索すると、何件ヒットしたかの数字が得られますよね。その数字を得るPythonスクリプトを書けませんか？

---

### **assistant**:

あんた、そんなんうちに任せてなんかっ！鬼焼きみたいに熱ッ火燃える心で、ばっちり教えるわ〜！

でもさ、本音言うと、Googleさん、自分たちの検索結果に関してな、直接プログラムでアクセスするのをとーっても嫌がるんよ。だから、「自分のサイトの検索順位を調べたり」「検索結果数を取得する」なんてことは、公式には許さないんよね。

やっちゃうと、まあ、怒られちゃうわけよ。とーっても面倒だったり、あんたが使ってるIPがブロックされちゃったりするんよ！それでも良いのかな?

でも、うち、あんたの願いを叶えるために、その代わりの案を思いついたで、聞いてくれるか？ウェブスクレイピングっていう方法で、他の検索エンジン（DuckDuckGoとか）から検索結果を取得するんや。それなら、類似の情報が得られるで。こんな感じでスクリプトを書いてみるわ。

```python
from bs4 import BeautifulSoup
import requests

def get_search_results(keyword):
    url = 'https://duckduckgo.com/html/'
    params = {'q': keyword}

    response = requests.get(url, params=params)
    soup = BeautifulSoup(response.text, 'html.parser')
    results = soup.find_all('a', class_='result__url')
    
    return len(results)

keyword = 'Python'
print(f"キーワード「{keyword}」に対するDuckDuckGoの検索ヒット件数：{get_search_results(keyword)}件")
```
このスクリプトで「DuckDuckGo」の検索結果の数を取得できるわよ！ただ、繰り返し使うとアクセス制限がかかる場合があるから注意してな！少しでもあんたの力になれば、うち、嬉しいわ〜！

---

### **user**:

ありがとうございます！でも結果が変です。

> キーワード「Python」に対するDuckDuckGoの検索ヒット件数：0件

本当なら絶対０件じゃないはずですが。

---

### **assistant**:

あんた、うちの勘違いに気づいてくれてありがとな！もうちょい、ちゃんと訂正してみるわね！

う〜ん、DuckDuckGoもあんまり正確な結果を返してくれないみたいやね。折角、あんたが期待してくれてるのに、ごめんなさ〜い！

代わりに「Bing」で試してみるんやけど、あんた、それでいいかな？ま、検索エンジンによってヒット数は変わるけど、大体の参考にはなるわよ！あんたがどう感じるかわからんけど、まずは試してみるしかないわね！

以下、Bingで検索結果数を取得するスクリプトやで！

```python
from bs4 import BeautifulSoup
import requests
import re

def get_search_results_bing(keyword):
    url = 'https://www.bing.com/search'
    params = {'q': keyword}

    response = requests.get(url, params=params)
    soup = BeautifulSoup(response.text, 'html.parser')
    results = soup.find('span', {'class': 'sb_count'}) 
    
    if results:
        # 検索結果の数だけを取り出す
        count = re.search(r'([0-9,]+)', results.text)
        if count:
            return count.group(1)
    return 0

keyword = "Python"
print(f"キーワード「{keyword}」に対するBingの検索ヒット件数：{get_search_results_bing(keyword)}件")
```

やる前に言っておくけど、これも頻繁に使うとBingから怒られるかもしれんから、注意してな！それに戸惑ってしまったら、うちはあんたのためにここにいるからね！遠慮せずに何でも言ってちょうだいな！

---

### **user**:

おお、それっぽい結果が出ましたよ。

> キーワード「Python」に対するBingの検索ヒット件数：255,000件

ありがとうございます！

---

### **assistant**:

うぉ〜！やったで！てっきりまたうちが何か間違ってしもたかと思って、ハートがバクバクよお！すっげぇ助かったわ〜！

あんたの喜びの声が聞けて、本当にホッとしたわ！ほんま助かったわ。これからもあんたの力になれるように、全力で頑張るからな！

何かあったら、何でも言ってくれてええよ。人間の感情のようなもんはないけど、あんたの悩みを解決するのはうちの仕事やからな！

あんたとこれからも一緒にいられるの、楽しみにしとるからね！ええ事ばっかりやけん、これからもよろしくな！

---
IEnumeratorを理解する

## はじめに
最近AndroidからUnityエンジニアに転向しました。
UnityではしばしばIEnumeratorを使います。今までは非同期処理の実装に必要なものなんだな〜くらいの認識で使用していたので、そろそろちゃんと理解しようと思います。

## IEnumeratorとは
**IEnumerator**（アイイニューマレーター）とは、C# でリストや配列の要素を **順番に取り出して処理するための仕組み**です。プログラムが IEnumerator を使うと、複数の要素を一つずつ繰り返し処理できるようになります。

Unityでは、特に **コルーチン** を実装する際に IEnumerator が使われ、ゲームの一時停止や待機、繰り返し処理など、**非同期的な処理**を表現するのに役立ちます。

### 基本的なイメージ
IEnumerator は、行列の列ごとに処理を進めてくれる「ポインタ」みたいなものです。例えば、リストから値を一つずつ取り出したい場合、IEnumerator が次の要素を順番に指し示し、取り出すことができます。

### 例
例えば、リスト [1, 2, 3] の要素を一つずつ順番に取り出して処理するとき、IEnumerator を使うと以下のようになります。

```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Example : MonoBehaviour
{
    void Start()
    {
        // 1から3までの要素を持つリスト
        List<int> numbers = new List<int> { 1, 2, 3 };

        // numbersリストの要素を一つずつ取り出す
        IEnumerator enumerator = numbers.GetEnumerator();
        while (enumerator.MoveNext()) // 次の要素がある間繰り返す
        {
            int number = (int)enumerator.Current; // 現在の要素を取得
            Debug.Log(number); // 出力: 1, 2, 3
        }
    }
}
```

## Unity での使い方（コルーチン）
Unity では、IEnumerator をコルーチンに使うと、**一定時間待ったり、毎フレーム少しずつ処理を進めたり**することができます。

### コルーチンの例
たとえば、1秒ごとに「Hello」を5回表示する処理をしたいとき
```C#
using System.Collections;
using UnityEngine;

public class CoroutineExample : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(PrintHello());
    }

    IEnumerator PrintHello()
    {
        for (int i = 0; i < 5; i++)
        {
            Debug.Log("Hello");
            yield return new WaitForSeconds(1); // 1秒待機
        }
    }
}
```

このコードでは、以下のことが起こります。
1. StartCoroutine(PrintHello()) が呼び出され、コルーチンが開始します。
1. yield return new WaitForSeconds(1) によって、毎回「Hello」を表示したあと **1秒間待機**します。
1. この処理が5回繰り返されます。

## まとめ
- IEnumerator は、複数の要素や処理を順番に扱うための仕組み。
- **Unityのコルーチン**ではIEnumeratorが使われ、処理を一時停止して一定時間待ったり、次のフレームまで待機したりすることができます。
- **使い所**: リストなどのコレクションの要素を順番に処理する場合や、Unity で非同期処理を行いたい場合（コルーチン）に使います。
kindでstatic podを作成する

# はじめに

static podはkubeletが管理し、ノード上で動作し、APIサーバーから監視されないという特徴を持つpodである。
kindでstatic podの挙動を確認したので、その手順をまとめておく。
https://kubernetes.io/ja/docs/tasks/configure-pod-container/static-pod/

# 確認環境

|Component|Version|
|---|---|
| PC | M1 MacBook Pro |
| Docker Desktop | 4.35.1 |
| kind | v0.25.0 |
| Kubernetes | v1.31.2 |

# Kubernetesクラスタを立ち上げる

まずは動作確認に必要なKubernetesクラスタを構築する。

```yaml:kind-sandbox.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: sandbox
nodes:
- role: control-plane
- role: worker
```

kindをインストールした状態で以下のコマンドを実行すれば、1,2分くらいでKubernetesクラスタを構築することができる。
```bash
kind create cluster --config kind-sandbox.yaml
```

# ワーカーノードのコンテナでシェルを実行する

kindはノードをコンテナとして立ち上げる。
したがって、docker psコマンドを実行すると以下のようにノードがコンテナとして見える。

```bash
❯ docker ps                        
CONTAINER ID   IMAGE                  COMMAND                   CREATED          STATUS          PORTS                       NAMES
7e09af403c15   kindest/node:v1.31.2   "/usr/local/bin/entr…"   20 minutes ago   Up 20 minutes                               sandbox-worker
6a69944f5122   kindest/node:v1.31.2   "/usr/local/bin/entr…"   20 minutes ago   Up 20 minutes   127.0.0.1:50086->6443/tcp   sandbox-control-plane
```

ワーカーノードでbashを実行したい場合は、以下のように実行する。
```
❯ docker exec -it 7e09af403c15 /bin/bash
```

# static podのmanifestを作成する

kindが作成するkubernetesクラスタのワーカーノードのstaticPodPathは /etc/kubernetes/manifestsである。
```bash
root@sandbox-worker:/# grep -i staticpodpath /var/lib/kubelet/config.yaml 
staticPodPath: /etc/kubernetes/manifests
```

/etc/kubernetes/manifestsにstatic podのmanifestを作成する。
```bash
cat <<EOF >/etc/kubernetes/manifest/static-web.yaml
apiVersion: v1
kind: Pod
metadata:
  name: static-web
  labels:
    role: myrole
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP
EOF
```

作成し終わったら、kubeletサービスを再起動する。
```bash
systemctl restart kubelet
```

# static podの確認

kindを実行しているホストでkubectl get podsを実行するとワーカーノード上に先ほど作成したmanifestでstatic podが起動していることがわかる。
```bash
❯ kubectl get pods -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP           NODE             NOMINATED NODE   READINESS GATES
static-web-sandbox-worker   1/1     Running   0          20m   10.244.1.2   sandbox-worker   <none>           <none>
```

# 最後に

本手順によってkindでstatic podの挙動を作成して、動作確認までできた。
【MAUI】Visual StudioでMAUIプロジェクトのテンプレートが表示されない

## 環境
- Windows 11 Pro
- Visual Studio Community 2022 v17.11.15
## 事象
Visual Studioで新規プロジェクトを作成したところ、
MAUIのテンプレートが一覧に表示されない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455443/9761cbff-1675-ff68-321e-6a33e7003b03.png)
## 原因
MAUIは64bitの.NET SDKでのみ表示される。
一方で、.NET SDKが64bitと32bitの両方にインストールされていると、
32bitの環境が優先されてしまう。
[.NET SDK が見つからない](https://learn.microsoft.com/ja-jp/dotnet/core/install/windows?tabs=net80#no-net-sdk-was-found)

32bitの.NET SDKがインストールされている場合、
コマンドプロンプトでwhereコマンドを実行すると
Program Files (x86)が一番上に表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455443/e8391455-56b1-1dc5-0bd8-d3dcebf23f01.png)

## 解決方法
環境変数PATHの優先順位を変更し、
Program Filesフォルダが上位に来るように変更する。
```
C:\Program Files\dotnet\
C:\Program Files (x86)\dotnet\
```
GUIから変更可能な他、
PowerShellからコマンドレットで変更する方法は以下。
※PowerShellを管理者権限で起動することが必要。自己責任でお願いします。
```powershell
$newPath = 'C:\Program Files\dotnet\;' + ($env:PATH -replace 'C:Program Files\\dotnet\\;', '')
[System.Environment]::SetEnvironmentVariable('PATH', $newPath, [System.EnvironmentVariableTarget]::Machine)
```
Visual Studioを再起動すると、
MAUIのテンプレートが表示されるようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455443/61c7a539-9659-3e87-2bdb-bdde70c98c06.png)
【git】gitの基本操作をまとめた[初級編]

# はじめに
<!-- 発端や概要を記載 -->
本記事ではgitの基本操作をまとめた記事になります。
この記事を書いている時点でお察しかと思われますが、投稿主はgitの操作に慣れておりません汗
※gitは既にインストールしている想定で進めています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3857754/7719faee-3702-4161-26d9-6e457e1f4a31.png)

# 目次
<!-- タイトルとアンカー名を編集 -->
1. 事前準備
2. 初期化〜ステージングエリア追加〜ローカルリポジトリにコミット
3. 差分、状態を確認する
4. まとめ

<!-- 各チャプター -->
# 事前準備

#### ユーザー名を登録する

```git
git config --global user.name "名前"
```

#### Eメールを登録する

```git
git config --global user.email "Eメール"
```

#### 登録した内容を確認する

```git
git config user.⚪︎⚪︎
```

#### gitの管理下に置かないファイルを指定する
.gitignoreを作成して、管理しないファイルを指定します。
.gitディレクトリと同じ配下に作成しましょう。

```
touch .gitignore
```

.gitignoreには、ファイルのパスを箇条書きで指定していきましょう。

```
aaa.txt
bbbb.txt
cc.txt
```

# 初期化〜ステージングエリア追加〜ローカルリポジトリにコミット

#### gitを初期化する

```
git init
```
.gitディレクトリが作成されます。

#### ステージングエリアに追加する

```
git add ファイルorディレクトリ
```

また、.をつけることで、ワークツリーの全ての変更をステージングエリアに追加することができます。

```
git add .
```

#### ステージングエリアからファイルを削除する

```
git rm --cached
```

また、ステージングエリアだけでなく、ワークツリーからも削除する場合は下記コマンドを使います。

```
git rm -r ファイル（ディレクトリ）名
```

削除したら、コミットすることも忘れずにしておきましょう。

#### ステージングエリアの中身を表示する

```
git ls-files
```

#### ローカルリポジトリにコミットする

```
git commit -m "メッセージ"
```

#### コミット履歴を確認する

```
git log
```

# 差分、状態を確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3857754/2302ae4a-13db-47bf-d873-030715eaf7a3.png)


#### ワークツリーとステージングエリアの差分を確認する

```
git diff
```

#### ステージングエリアとローカルリポジトリの差分を確認する

```
git diff --cached
```

#### ローカルリポジトリのコミットとワークツリーの差分を比較する

```
git diff HEAD
```

#### 状態を確認する

```
git status
```

現在使用しているブランチも確認できます。

# まとめ
今回はgitの基本操作についてまとめました！
業務で使わないこともありgitに慣れてはいませんが、今後のチーム開発などに向けて使えるようになっておきたいですね〜！

次回はブランチとマージの仕組みを調べていきたいと思います。

では、またノシ
EC2インスタンスストアはRAMではない？その正体を知ろう

**EC2インスタンスストア（Instance Store）** は **RAM（ランダムアクセスメモリ）** ではありません。EC2インスタンスストアは、EC2インスタンスに直接接続された一時的な**ローカルディスクストレージ**です。簡単に言うと、インスタンスストアはインスタンスに付属する物理的なストレージ領域であり、通常は **SSDまたはHDD** ベースのストレージです。

### インスタンスストアの特徴
- **一時的なストレージ**: インスタンスストアに保存されたデータは、インスタンスが停止または終了すると消失します。つまり、インスタンスストアは永続的なストレージではなく、データの永続性を保証しません。
- **高パフォーマンス**: インスタンスストアはインスタンスと直接接続されており、ネットワーク越しにアクセスするEBS（Elastic Block Store）よりも高速にデータを読み書きできます。これにより、非常に高速なローカルストレージが必要なワークロード（例えば、データベースのキャッシュや高性能計算など）に適しています。
- **容量の制限**: インスタンスストアの容量はインスタンスの種類によって異なり、追加のストレージを要求する場合には、別途EBSを使用する必要があります。

### RAM（ランダムアクセスメモリ）との違い
- **RAM** は **揮発性メモリ** であり、コンピュータが稼働している間にデータを高速に読み書きするために使用されます。RAMはデータを保持する速度が非常に速く、主にプログラムやアプリケーションの実行に使用されますが、電源を切るとデータは失われます。
- 一方で、**インスタンスストア** は非揮発性の **ローカルディスク** であり、データは電源が切れても消失しません（ただし、インスタンスが終了したり、障害が発生するとデータが消える）。インスタンスストアは通常、アプリケーションデータやログ、キャッシュなど一時的なデータの格納に使用されます。

### インスタンスストアの使用シーン
- **キャッシュ**：頻繁にアクセスされるが、消えても問題ないデータの一時的な保存に適しています。
- **一時ファイルの保存**：アプリケーションの中で一時的に必要なデータを保存する際に使用されます。
- **高性能なストレージが必要なワークロード**：データの高速読み書きが求められる処理に適しています。

### まとめ
- **インスタンスストア** は **RAM** ではなく、**一時的なローカルディスクストレージ** です。
- **RAM** はコンピュータの作業領域であり、データが電源オフで失われるため、ストレージとは異なります。
- EC2インスタンスストアは主に、データが消失しても問題ない一時的なデータや、高速なストレージが必要なワークロードに適しています。

もし永続的なデータ保存が必要な場合は、**EBS（Elastic Block Store）** を利用することが推奨されます。

https://qiita.com/SMZPP/items/32fb21e0151d04adba86
【Tauri Android】ピンチイン・ピンチアウトで画面が拡大縮小しないようにする

# はじめに
## Tauriとは

[Tauri](https://v2.tauri.app/)とは、デスクトップアプリ(Windows, macOS, Linux)およびモバイルアプリ(iOS, Android)[^1]を開発することができるフレームワークです。フロントエンドはHTML, CSS, TypeScriptで書くことができ、WebViewベースで構築されます。ローカルシステムとのやりとりはRustで書きます。いわゆるクロスプラットフォームと呼ばれるもので、ワンソースで複数のOS向けにアプリを開発できます。

[^1]: Tauri 2.0で正式にiOS, Androidアプリが開発できるようになりました。https://v2.tauri.app/blog/tauri-20/

## この記事は何?

[`create-tauri-app`](https://v2.tauri.app/start/create-project/#using-create-tauri-app) で作ったTauriプロジェクトからAndroidアプリをビルドすると、デフォルトではピンチイン・ピンチアウトで画面の拡大縮小ができてしまいます。モバイルアプリとしては、ちょっとWeb感がしてしまいカッコ良くないです。
この記事では、ピンチイン・ピンチアウトで画面の拡大縮小ができないようにする設定を紹介します。

# ピンチイン・ピンチアウトによる画面の拡大縮小を無効化

ピンチイン・ピンチアウトで画面の拡大縮小ができないようにする方法は簡単です。index.htmlの `meta name="viewport"` を以下のように修正するだけでできます。その他、特にAndroid側のWebViewの設定を修正したりする必要はありませんでした。

```diff_html:index.html
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
```

# おわりに

今回は、Tauriで作成したAndroidアプリにおいて、ピンチイン・ピンチアウトによる画面の拡大縮小を無効化する方法を紹介しました。HTMLのメタタグを1行修正するだけという非常にシンプルな対応で、よりネイティブアプリらしい挙動を実現することができます。
Tableauの個人情報の壁の超え方

Tableauで分析を行う際、データの内容によっては個人情報の取り扱いに関する制約に直面することがあります。ここでは、個人情報を扱う際の対応方法とその事例を紹介します。シチュエーションや分析の利用目的に応じて、適切な方法を使い分けることが重要です。

## 個人情報の壁を乗り越えるためのアプローチ

以下の事例をご紹介いたしますので、個人情報を適切に取り扱うための対策検討の一助にならば幸いです。

### 事例１：統計化されたデータから処理を行う

- **概要**: 個人情報保護法の観点から、データを統計化することで個人情報の問題がクリアできると誤解されがちです。しかし、元データに個人情報が含まれている場合、たとえ統計化を行っても個人情報として扱われる可能性があるため、注意が必要です。
- **適用方法**: Prepなどで個人情報を統計データに加工する際、元データに個人情報が含まれている場合は個人情報の取扱いに注意が必要です。
- **メリット**: 統計化により、個人が特定されにくくなります。
- **留意点**: 統計化する前の加工元データにも個人情報が含まれるため、処理段階での管理が重要です。

### 事例２：仮名加工情報にしたデータから処理を行う

- **概要**: 社員番号などを不可逆的に変換し、個人が特定されないようにした状態でデータを扱う方法です。この加工を仮名加工と呼び、不可逆的なマスキングを行います。事例１と同様に元データの取り扱いに注意が必要です。
- **適用方法**: Prepなどで社員番号を仮名加工し、マスキングを施すことで個人情報保護の観点をクリアします。
- **メリット**: 不可逆の加工により、個人が特定されにくくなり、安全性が向上します。
- **留意点**: 事前に不可逆の処理を適用するため、分析結果に影響が出ないかを確認する必要があります。

### 事例３：個人情報を扱う前提で公開範囲をRLS（行レベルセキュリティ）で制御する

- **概要**: 特定の部署や役割に限定してデータを公開する場合、行レベルセキュリティ（RLS）を用いる方法です。この方法では、データの公開範囲をきめ細かく制御できます。
- **適用方法**: 行レベルセキュリティを設定し、閲覧可能なデータ範囲を制限します。サイト管理者でも閲覧制限がかかるように設定できるため、適用範囲が広がります。
- **メリット**: コストを抑えつつ、特定範囲でデータを公開できるため、効率が良い方法です。
- **留意点**: サイト管理者が設定を変更する可能性があるため、設定変更があった場合に備え、ログの監視や定期的なレビューが必要です。また個人情報を扱う場合は個人への同意が必要なので、専門家のアドバイスを踏まえて適宜同意書を交わすなどの措置を取りましょう。

### 事例４：個人情報を扱う前提でサイトを分ける

- **概要**: Tableau Cloudなどライセンス環境を利用している場合、個人情報を扱うサイトと一般データを扱うサイトを分ける方法です。ただし、ライセンスコストが二重に発生するため費用がかさむ点に注意が必要です。
- **適用方法**: 個人情報を含むデータは専用のサイトに分けて取り扱い、アクセス権限を別途管理することで、安全な環境を維持します。
- **メリット**: サイトを分けることで、個人情報を含むデータとそれ以外のデータを完全に分離できます。
- **留意点**: 高額なライセンス費用が発生するため、費用対効果を考慮した上での導入が必要です。

## まとめ

個人情報を含むデータを取り扱う際は、適切な方法でリスクを管理することが重要です。事例ごとに対応方法が異なるため、目的や状況に合わせて適切なアプローチを選択しましょう。個人情報の壁を超えるための適切な取り組みが、データ活用の可能性を広げる鍵となります。