OmniAICreator/Qiita-1.07M huggingface dataset:
[Django REST framework] ModelViewSet response に集計項目 (annotate) を追加する

# 概要

- ModelViewSet に annotate で集計した項目を追加する
    - ModelViewSet の queryset で annotate する
    - Serializer で `read_only=True` な field を追加する
        - annotate で指定した名称と Serializer の field 名を一致させる
- ついでに、対象の Model と集計する対象の Model にリレーションが無い例で試してみる
- Django 4.2 で動作確認済み

# サンプルプロジェクト

- ブログシステム
- 下書き (DraftPost) と、公開済み記事 (PublishedPost) を分離
- DraftPost を公開・承認する (approve) ときには
    - DraftPost に対応する (pk:title が一致する) PublishedPost があればそれを更新し、なければ作成する
- DraftPost を get する際には、対応する PublishedPost が存在するか (has_published_post) をレスポンスに含める
- (ModelViewSet の検証のためだけにぱっと作ったプロジェクトなので、ブログシステムを開発する際にこのような DB 設計にするのが妥当であるかとかは全く考えてないです。)

## Model

```python
class PublishedPost(models.Model):
    title = models.CharField(max_length=200, primary_key=True)
    content = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    category = models.ForeignKey(
        Category, on_delete=models.SET_NULL, null=True, blank=True
    )
    tags = models.ManyToManyField(Tag, blank=True)
    version = models.PositiveIntegerField(default=1)

    def __str__(self):
        return self.title


class DraftPost(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    category = models.ForeignKey(
        Category, on_delete=models.SET_NULL, null=True, blank=True
    )
    tags = models.ManyToManyField(Tag, blank=True)

    def __str__(self):
        return self.title
```

## Serializer

```python
class DraftPostSerializer(serializers.ModelSerializer):
    has_published_post = serializers.BooleanField(read_only=True)
    tags = TagSerializer(many=True, read_only=True)

    class Meta:
        model = DraftPost
        fields = "__all__"
```

## View

```python
class DraftPostViewSet(viewsets.ModelViewSet):
    queryset = DraftPost.objects.annotate(
        has_published_post=Exists(PublishedPost.objects.filter(title=OuterRef("title")))
    ).prefetch_related("tags")
    serializer_class = DraftPostSerializer

    @action(detail=True, methods=["post"])
    def approve(self, request, pk=None):
        draft_post = self.get_object()
        published_post, created = PublishedPost.objects.update_or_create(
            title=draft_post.title,
            defaults={
                "content": draft_post.content,
                "author": draft_post.author,
                "category": draft_post.category,
                # Increment the version number by 1 to reflect the new version of the published post
                "version": F("version") + 1,
            },
        )
        published_post.tags.set(draft_post.tags.all())
        return Response({"status": "approved"}, status=status.HTTP_200_OK)
```

## 以下からためせます

[h-amemi/drf_sample_annotate_viewset](https://github.com/h-amemi/drf_sample_annotate_viewset)
【超基礎】TypeScript、タプルについて

# 前提
この記事は、初学者の私が、サバイバルTypeScriptで学んだこと+調べたことをまとめたものになります。

従って、経験則に基づいた発言ではないため、一部慣習とは違っていたり、認知にずれがあったりする可能性がありますので、ぜひコメントで指摘していただけると幸いです。

https://typescriptbook.jp/

# 環境
記事内のコードは以下の環境で動作確認済みです。

- Node.js: v22.10.0
- TypeScript: Version 5.6.3

# タプルとは？
- **異なる型**の値を要素として持つことができる配列
- **型の種類、型の順番、要素の数が固定**される
- インデックスや分割代入による値へのアクセスが可能
- Promise.all()との併用により並列処理を実装できる
:::note warn
pythonにおけるタプルは、**値を変更できない配列(リスト)** を指すが、

TypeScriptにおけるタプルは、**値の変更はできる**。
:::

# 配列との違い
|| 配列 | タプル |
|:-:|:-:|:-:|
|複数の型の格納| 非推奨 <br>ユニオン型を使えば**出来ないことはない**  | OK  |
|長さの変更|OK　（`.push()`メソッドによる追加）　   |   NG|
|変数の順序|特に指定はなし（ユースケースによる)|宣言時の型の順番に従う|
|Array<T>による宣言|可能|不可|


# タプルと型
- タプル宣言時に[type,type...]の形式で型注釈を行う
- 同様の形式で型エイリアスの宣言も可能
- 型の順番は固定される

# 実装例
```typescript:タプル
//宣言
const human:[string,number] = [ "taro", 20 ];

//インデックスによるアクセス
console.log(human[0]); //=>taro
console.log(human[1]); //=>20

//分割代入
//型注釈が無くてもエラーは出ない
const [name,age]:[string,number] = human;
console.log(name); //=>taro
console.log(age); //=>20

//値の追加(NG)
human.push(5) //=> Error
```
```typescript:タプルを使った並列処理
//サバイバルtypescriptからの引用
//https://typescriptbook.jp/reference/values-types-variables/tuple

//タプルとPromise.allによる並列処理
//stringとnumberが格納されたタプルを取得できる
//完了までの所要時間は5秒
const tuple: [string, number] = await Promise.all([
  takes3Seconds(), //処理に 3 秒かかり、string を返す関数
  takes5Seconds(), //処理に 5 秒かかり、number を返す関数
]);
```

# まとめ
以上になります。

慣例から外れた部分があれば指摘していただけると幸いです！！
WordPressサーバー間データ移行手順

## はじめに
WordPressでサーバー間データ移行を行った際の手順を記録する
この手順は、データ移行プラグインを用いず、データベースとファイルを手動で移行する方法
また、移行元と移行先でPHPとWordPressのバージョンが異なる


## 環境情報
### 移行元サーバー
PHP：5.6.40
WordPress：5.1.19

### 移行先サーバー
PHP：8.3.14
WordPress：6.6.2

## 前提条件
・移行先サーバーには、対象バージョンのWordPressがすでにインストールされている
・移行元と移行先のサーバーで基本的なディレクトリ構造は同じ
・移行元と移行先でドメイン名は同じ
　（異なる場合でも移行可能だが、データベースや```wp-config.php```の調整が必要）

## 移行手順
### 1.DBをエクスポートする
移行元サーバーのデータベースにアクセスし、データをエクスポートする
→ phpMyAdminなどのGUIツールを使うと簡単です
#### 対象テーブル
・```wp-config.php```において```$table_prefix```と同じ接頭辞のテーブル(大体```wp_```が接頭辞)
　→ マルチサイトを設定している場合はマルチサイトのテーブルも移行する必要がある
※ よく分からない場合は、すべてのテーブルをエクスポートしておけば問題ない

---
### 2.ファイルをダウンロードする
移行元サーバーから```wp-content```配下の以下のフォルダをダウンロードする
- themes（テーマ関連）
- plugins（プラグイン）
- uploads（メディア関連）

※ プラグイン関連で```wp-content```配下に別途フォルダがある場合は、それもダウンロードする必要がある

---
### 3.エクスポートしたデータをインポートする
1.でエクスポートしたデータを移行先のDBにインポートする
この場合、WordPressインストール時の初期データは削除していい

#### ※移行元と移行先でドメイン名が異なっている場合
移行元と移行先でドメイン名が異なっている場合は以下のDBのデータを修正する必要がある
- ```wp_options```テーブル
    - ```option_name```が```siteurl```のレコード：```option_value```を新しいドメインに修正
    - ```option_name```が```home```のレコード：```option_value```を新しいドメインに修正
- ```wp_siteテーブル```
    - ```domain```の値を新しいドメインに修正
- ```wp_blogsテーブル```
    - ```domain```の値を新しいドメインに修正

##### マルチサイトの場合の追加修正
- ```wp_2_optinosテーブル```（接頭辞はマルチサイトの設定に依存する）
    - ```option_name```が```siteUrl```のレコード：```option_value```を新しいドメインに修正

---
### 4.ファイルをアップロードする
2.でダウンロードしたファイルを移行先のwp-content配下に同じようにアップロードする
WordPressインストール時に作成された以下のフォルダは、上書きして問題ない
- ```themes```
- ```plugins```
- ```uploads```

---
### 5.wp-config.phpを修正する
移行先の```wp-config.php```必要に応じて修正する
- DBの接続情報はWordPressインストール時に設定されているもので正しいはず
- ```$table_prefix```はインポートしたDBの接頭辞に修正する必要がある

#### 注意点
また、移行元のサーバーで以下の設定がある場合は、必要に応じて移行先にも追加する
- ```WP_AUTO_UPDATE_CORE```（自動更新の設定）
- ```WP_ALLOW_MULTISITE```（マルチサイト設定）

---
### 6.サイトにアクセスする
正常にページが表示されていれば完了

## おわりに
これでデータ移行手順は完了

データ移行はこの手順で割とすんなりできたが、PHPのバージョン違いによって色々エラーが発生して修正に苦労した
その話は次回書くつもり
→ [次回](https://qiita.com/matsumura_zyyx/private/c43e5ee85e7a893b0c3a)
WordPressサイトのPHPバージョンアップデートに伴うエラー

## はじめに
[こちらの記事](https://qiita.com/matsumura_zyyx/private/bd50ef7295d2d3238108)で、WordPressのサーバー間データ移行を行った
その際に移行元と移行先でPHPのバージョン違いなどにより発生した
本記事ではその修正方法について記す

## 環境情報
### 移行元サーバー
PHP：5.6.40
WordPress:5.1.19

### 移行先サーバー
PHP:8.3.14
WordPress:6.6.2

## エラーの修正
### create_functionの廃止
create_functionメソッドはPHP7.2で非推奨となり、PHP8で削除された
PHP8以降では代わりに無名関数を使用する必要がある
```diff_php
- add_filter( 'フィルター名', create_function('$a', "return '<p>これはテストです</p>';") );
+ add_filter( 'フィルター名', function($a){return '<p>これはテストです</p>';});
```

#### 参考
- [create_functionメソッド](https://www.php.net/manual/ja/function.create-function.php)
- [無名関数](https://www.php.net/manual/ja/functions.anonymous.php)


### エスケープされない「･･･」の記述
「･･･」がエスケープされずそのまま使用されている場合、PHPは未定義の定数として解釈してエラーとなる
PHP7以降では未定義の定数に対して厳格なエラーが出やすくなっているため、発生しやすい
（以下の記述はそもそもエラーの可能性が高そうだが...）
```diff_php
- <p><?php $title = 'test'; echo $title. ･･･ ; ?></p>
+ <p><?php $title = 'test'; echo $title. '･･･' ; ?></p>
```
### &= newの記述
PHP 5以降、新しいオブジェクトを作成する際に参照渡しを明示する必要はなくなった
```&= new```という書き方は非推奨となり、PHP 7以降ではエラーになる
```diff_php
- <?php $test =& new test_class();
+ <?php $test = new test_class();
```

#### 参考
- [PHP7の変更点](https://www.php.net/manual/ja/migration70.incompatible.php#migration70.incompatible.other)

### 短縮タグの変更
PHP5.3以下ではPHPのshort_open_tagがデフォルトでOnとなり、短縮タグが利用できていた
PHP7以降ではshort_open_tagがデフォルトでOFFとなり、そのままだとエラーになる
そのため、short_open_tagがOnにするか短縮タグを利用しないようにする必要がある
```diff_php
- <? if($bool): ?>foo<? endif; ?>
+ <?php if($bool): ?>foo<?php endif; ?>
```
CSSは自由、だから難しい。 - マージン設計で学んだこと

この記事は [デジタルキューブ ＆ ヘプタゴン Advent Calendar 2024](https://qiita.com/advent-calendar/2024/digitalcube-heptagon "デジタルキューブ ＆ ヘプタゴン Advent Calendar 2024") の 12月11日分の記事です。

---------------------------------------

こんにちは。4月からプロダクトデザインチームでコーディングをがんばっているNおです。今日は「CSSは自由、だから難しい。」というお話をします。
<br>
## CSS設計との出会い
CSSは同じ見た目を実現するのに複数の方法があります。

経験豊富なエンジニアであれば、メンテナンスのしやすさを考慮して最適な方法を選べるのでしょうが、実務経験の浅い自分にはその判断が難しかったり、そもそも知っている実装方法が限られているなどの問題があります。

先輩の書くCSSと自分の書くCSSを見比べて「先輩はどういう意図があってこういう書き方をしているのだろう？」という疑問を抱えていたときに出会ったのが「CSS設計」です。

## 余白の設計
CSS設計を学ぶ中でとくに興味深かったのは「余白の設計」についてです。
余白の方向を統一することで、コンポーネントを積み重ねるときの予測がしやすく、一貫性のある余白設計ができるという考え方でした。
<br>

**Nお「なるほど！余白の方向を統一すればいいんだな…！」**

![yaruki_aru_casual_woman.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3940647/1875235f-95f3-6c68-13fd-44c14e72b672.jpeg)

マージンを下方向で統一することを覚えたNおは、嬉々として実践に入りました。

## 実践編
実際に直面したコードの例です。
左側が画像、右側がテキストという、Webサイトでよく見るレイアウトです。

```html:block.html
<div class="block">
	<div class="block__content">

		<figure class="block__figure">
			<img src="sample-image.jpg" alt="sample image">
		</figure>

		<div class="block__body">
			<h3 class="block__heading">タイトル</h3>
			<div class="block__description">説明文</div>
			<div class="block__button"><a href="#">ボタン</a></div>
		</div>

	</div>
</div>
```
要素間の距離は全部 `margin-bottom` で書いてやるぜ！と意気込んでいたところで問題が発生します。

**このボタンは「ある場合」と「ない場合」があるのです。**
<br>
え？じゃ、じゃあ、説明文が一番最後の要素になったときにだけ `margin-bottom` を打ち消す……とか、かなぁ………どうやって書こう…………？
<br>
答えは単純です。
<br>
<br>
<br>
**先輩「ボタンに `margin-top` をつければいいだけです。」**

![business_man1_4_laugh.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3940647/f661b78a-055d-faaa-0c4a-0215760ec62a.jpeg)

ええ、本当に、おっしゃる通りでございます。

学んだことに真っ直ぐすぎて足元が疎かになっていたことを反省しました。

## まとめ
結局のところ、CSSの設計ルールは便利な指針ですが、状況に応じて柔軟に判断することが大切だと学びました。ときには「マージンを上方向にとる」選択が、よりシンプルで保守しやすいコードになることもあります。

あくまで設計思想の一つでしかない「余白の方向を統一する」ことに囚われ、CSSの特徴である柔軟さを忘れてしまっていた初学者のお話でした。

## おまけ
ちゃんと下方向に統一で書くんだったらこうなるのかな？
```scss:block.scss
.block__description {
	margin-bottom: 0;
	&:has(+ .block__button) {
		margin-bottom: 20px;
	}
}
```
llama.cpp に12月2日に行われた変更点

Llama.cpp が12月2日からコンパイルの方法が変わりました。

commit 8648c521010620c2daccfa1d26015c668ba2c717
Author: Georgi Gerganov <ggerganov@gmail.com>
Date:   Mon Dec 2 21:22:53 2024 +0200

    make : deprecate (#10514)
    
    * make : deprecate

旧:   make
新:   cmake --build build

これだけだとつまらないので。
commit a6744e43e80f4be6398fc7733a01642c846dce1d (tag: b4011)
Author: Diego Devesa <slarengh@gmail.com>
Date:   Fri Nov 1 23:50:59 2024 +0100

    llama : add simple-chat example (#10124)
    
    * llama : add simple-chat example
    
    ---------
    
    Co-authored-by: Xuan Son Nguyen <thichthat@gmail.com>

使用方法
llama-simple-chat -m モデルファイル
他のサイトに移ったらサイトのタイトルを変える

この記事は「[大分高専 Advent Calendar 2024](https://adventar.org/calendars/10845 "大分高専 Advent Calendar 2024")」11日目の記事です．

## はじめに
これはニュージーランドについて調べているときに出会ったサイトです．

https://hanmersprings.co.nz/

このサイトがすごいと思ったのは，このサイトを開いたまま他のサイトに行くとタイトルが変わって，「Come back!」と表示されるところです．ぜひ試してみてください．
今回はこの機能をjavascriptで実装してみたいと思います．

## 実装してみる
他のサイトに移った時，タイトルが変わるという機能を実装したいです．
まず，タイトルを変えるには以下のようにtitle要素を取得し，textContentの値を変更すれば良いです．

```javascript
const title = document.querySelector('html title');
// 要素の取得
title.textContent = "ココに内容";
// 内容の変更
```

問題は他のサイトに移ったことをどうやって検知するか．
ここで登場するのが，blurイベントです．

https://developer.mozilla.org/ja/docs/Web/API/Element/blur_event

このイベントをWebページ全体（body要素）につけておくことで，そのサイトがフォーカスを失ったとき，つまり他のサイトにフォーカスが移ったときにこのイベントが呼ばれます．逆に，フォーカスを受け取ったときにはonfocusイベントが呼ばれます．


```javascript
    let body = document.querySelector('html body');
    body.onblur = () => {   
        title.textContent = "(｡-ˇ_ˇ-｡)";
    }
    body.onfocus = () => { 
        title.textContent = "ヾ(o ･∀･)ﾉwelcome back";
    }
```

実際の動作がこちら．

![画面収録-2024-12-11-0.07.37.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3947518/9d7fb21b-d286-c363-3cc3-e2a25c4eec37.gif)

他のページに移ったときに「(｡-ˇ_ˇ-｡)」が表示されています．成功です．

## おわりに
今回は，他のサイトにフォーカスが移ったときに呼び出される，onblurイベントを使って，タイトルを変えるという機能を実装しました．あまり実用性はないので，遊び心を加えたいときに使うと良いかなと思いました．
他のサイトに嫉妬してるみたいで可愛いですね．
Power Platform要求数の上限超過が引き起こす問題と対策

# 前提条件
- Microsoft 365 開発者プログラムをアクティブ化し、以下製品ライセンスを有効化する
    - Microsoft 365 E5 Developer
    - Microsoft Power Apps for Developer
    - Microsoft Power Automate Free
- Microsoft 365プランとなるので、パフォーマンスプロファイルは「低」に該当する
- 24時間あたりのPower Platform要求数の上限はユーザー単位で6,000だが、現在は移行期間中のため上限はフロー単位で10,000となる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/7c3c719b-c6b3-e5ea-a264-da990ee61e22.png)

Power Platform要求数の公式制限と移行期間の制限についての詳細は、以下記事をご参照ください。

https://learn.microsoft.com/ja-jp/power-platform/admin/api-request-limits-allocations#request-limits-in-power-automate


# 検証
Power Platform要求数の制限を超過した場合の挙動を確認するために、専用クラウドフローを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/ae5cb077-2efa-bc0c-ef8e-53300ee767db.png)

1. 初回実行
   - 実行時間：2時間49分16秒
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/0c59f428-2a79-9a03-0800-cb8943c6be1f.png)
   - フローデザイナーの詳細の［分析］からフローのアクション要求数を確認したところ、24時間あたりのPower Platform要求数の上限10,000を大幅に超過しています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/8151b9dd-d286-972e-5df0-ff59a9606998.png)


2. 再実行
   - 実行時間：5時間22分4秒
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/c1834722-c197-2045-3534-57eb39de7976.png)
   - 上限超過による実行エラーは発生しなかったものの、処理時間は初回実行時の約2倍となり、実行速度の低下が発生しています。また、2回目のフロー実行時には、フローのパフォーマンス警告メールが送信されています
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/2d1e38c2-af31-f9d8-ace4-f0fd268d294c.png)

# 原因と影響
フローの実行速度低下の原因は明白で、メール本文の記載にもあるように、Power Platform要求数がライセンス使用量に対して不十分であるためです。Power Platform要求数の上限超過は、フローの実行速度低下の原因になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/fd27c08a-94a4-a5ae-41fe-5a539a31128b.png)

https://learn.microsoft.com/ja-jp/troubleshoot/power-platform/power-automate/flow-run-issues/troubleshoot-slow-running-flows#cause-3-your-flow-executes-more-actions-than-the-daily-limits-for-your-plan

このフロー実行速度低下の制限は、スロットリング制限の対象にもなります。この制限に抵触すると、ありえんぐらい実行速度が低下します。実際に、2回目以降の実行時間は10時間以上もかかりました。<INS>スロットリング制限は24時間で解除されますが、14日間継続する場合は自動的にクラウドフローはオフになってしまいます。</INS>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/203d8e6c-764e-7396-b9d9-4b56217f631e.png)

フローデザイナーの詳細画面でスロットリング制限による警告が表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/2fbecaab-402e-b8f4-34bd-8ca7878fa7bd.png)

# 対策
対策にはさまざまなアプローチがありますが、個人的には有償ライセンスの購入が最も無難だと感じます。特に、移行期間中で制限が緩和されているからといって「まだ大丈夫だろう」と油断するのは禁物です。確実な対応で安心な運用を手に入れましょう！
- ライセンスの購入
  - Power Platform要求数の上限を引き上げるために、「Power Automate Premium」などのスタンドアロンライセンスを購入することが推奨されます。要求数の上限を増加させて、スロットリング制限のリスクを軽減させます
- フローの設計改善
  - フローの実行頻度の見直し、不要なアクションの削減をすることで、Power Platform要求数を抑えます
  - ［Do until］または［Apply to each］での反復処理をする項目の数を事前にフィルターしておくことで、ループ処理数を削減します
運用で使えるExcel日付自動入力

# 運用で使えるExcel日付自動入力
## はじめに

業務でExcelを使用していると、日付に関する計算や自動入力が必要になることが多々あります。
特に以下のようなケースでは、毎回手動で日付を入力するのは非効率的です：

- 月次レポートの作成時の対象期間入力
- 四半期報告における期首・期末の設定
- 年度処理における半期データの集計
- 週次進捗管理における日付更新

このような定型業務を効率化するため、Excel関数を使用した日付の自動計算方法をまとめました。

※ご紹介する関数の特徴としては営業日を作業日とするために休日が作業日に該当する場合は翌営業日もしくは前営業日にスライドする仕様となっています

## 事前準備

### 休日リストの作成

日付計算で祝日を考慮するために、別シートに休日リストを作成する必要があります[1]。

1. 新規シートを作成し、「休日」などの分かりやすい名前を付ける
2. 以下の列を作成:
   - 年月日
   - 休日名称
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326450/723cb02a-b30f-eb10-f3c7-224bffc1bda4.png)


### 半期リストの作成

年度半期の計算のために、別シートに半期の区切りを定義したリストを作成します。

1. 新規シートを作成（休日リストと同じシートでも可）
2. 以下の列を作成:
   - 半期リスト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326450/39c00e12-3170-bd56-cb75-f51f2c259cd4.png)

### テーブル化の手順

1. リストの範囲を選択
2. 「ホーム」タブ→「テーブルとして書式設定」をクリック
3. 「先頭行をテーブルの見出しとして使用する」にチェック
4. テーブル名を設定（例：「休日リスト」「半期リスト」）

## 使用する主な関数

本記事で紹介する日付計算では、主に以下の関数を使用します：

- DATE関数：年月日から日付を生成
- EOMONTH関数：月末日を取得
- WEEKDAY関数：曜日を判定
- TODAY関数：現在の日付を取得

それでは、頻度別に具体的な関数の使い方を見ていきましょう。

## 年次処理

年単位の処理で使用する日付計算です。

```excel
=LET(targetdate,$C$2,targetmonth,4,rundate,DATE(YEAR(EDATE(targetdate-1,-targetmonth))+1,targetmonth,1)-1,thisyeardate,WORKDAY(rundate,1,holiday[年月日]),IF(targetdate>thisyeardate,WORKDAY(EDATE(rundate,12),1,holiday[年月日]),thisyeardate))
```

## 年度半期処理
4月始まりの年度における上期（4月～9月）・下期（10月～3月）の初日と末日を計算します。

### 半期初日
```excel
=WORKDAY(MIN(IF(halfyear[半期リスト]>=$C$2,halfyear[半期リスト]))-1,1,holiday[年月日])
```
### 半期末日
```excel
=WORKDAY(MIN(IF(halfyear[半期リスト]>=$C$2,halfyear[半期リスト])),-1,holiday[年月日])
```

## 四半期処理
年度における四半期の初日と末日を自動計算します。
第1四半期（4-6月）から第4四半期（1-3月）までを自動判定します。

### 四半期初日
```excel
=LET(targetdate,$C$2,thisworkdate,WORKDAY(DATE(YEAR(targetdate),FLOOR.MATH(MONTH(targetdate),3)+1,1)-1,1,holiday[年月日]),IF(targetdate<=thisworkdate,thisworkdate,WORKDAY(DATE(YEAR(targetdate),CEILING(MONTH(targetdate),3)+1,1)-1,1,holiday[年月日])))
```
### 四半期末日
```excel
=WORKDAY(DATE(YEAR($C$2),CEILING(MONTH($C$2), 3)+1,0)+1,-1,holiday[年月日])
```

## 月次処理
月単位の処理で使用する日付計算です。
月初・月末・中間日（15日）の自動計算に対応します。

### 月初日
```excel
=LET(targetdate,$C$2,thismonthdate,WORKDAY(EOMONTH(targetdate,-1),1,holiday[年月日]),IF(targetdate>thismonthdate,WORKDAY(EOMONTH(targetdate,0)+1,1,holiday[年月日]),thismonthdate))
```
### 月末日
```excel
=WORKDAY(EOMONTH($C$2,0)+1,-1, holiday[年月日])
```
### 中間日（15日）
```excel
=LET(targetdate,$C$2,targetday,15,thismonthdate,DATE(YEAR(targetdate),MONTH(targetdate),targetday),IF(targetdate>thismonthdate,DATE(YEAR(targetdate),MONTH(targetdate)+1,targetday),thismonthdate))
```

## 週次処理
週単位の処理で使用する日付計算です。
週初め（月曜日）や週末（金曜日）の自動計算が可能です。
```excel
=LET(targetdate,$C$2,thisweekdate,WORKDAY(targetdate-WEEKDAY(targetdate,3)-1,1,holiday[年月日]),IF(targetdate>thisweekdate,WORKDAY(targetdate-WEEKDAY(targetdate,3)+6,1,holiday[年月日]),thisweekdate))
```

## 補足
- 日付計算では、DATE関数とEOMONTH関数を組み合わせることで柔軟な日付指定が可能です
- 曜日の判定にはWEEKDAY関数が便利です
- 日付のフォーマット指定は「ユーザー定義」で細かく設定できます
- これらの関数は数式を組み合わせることで、より複雑な条件にも対応できます

## まとめ
本記事で紹介した関数を活用することで、日付に関する定型業務を大幅に効率化できます。
特に定期的なレポート作成やデータ更新作業では、手作業による入力ミスも防ぐことができます。
ぜひ、実際の業務に合わせてカスタマイズしてご活用ください。
命名規約を上書きする

# 命名規約を上書きする
>Railsアプリケーションで`別の命名規約を使わなければならない場合`や、`レガシーデータベースを用いてRailsアプリケーションを作成しないといけない場合`は、デフォルトの命名規約を手軽にオーバーライドできます。
>

### テーブル名を変更
>ApplicationRecordは、有用なメソッドが多数定義されているActiveRecord::Baseを継承しているので、使うべきテーブル名を`ActiveRecord::Base.table_name=メソッドで明示的に指定`できます。

https://railsguides.jp/active_record_basics.html#:~:text=Rails%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A7,%22my_books%22%0Aend

```rb
class Book < ApplicationRecord
  self.table_name = "my_books"
end
```
```rb
irb(main):001:0> Book.table_name
=> "my_books"
```

```rb
class Book < ApplicationRecord

end
```

```rb
*********@******** % rails c --sandbox
....
irb(main):001:0> Book.table_name
=> "books"
```
### テスト用のテーブル、カラム名も上書きできる
>テーブル名をこのように上書き指定する場合は、テストの定義でset_fixture_classメソッドを使い、フィクスチャ(my_books.yml)に対応するクラス名を別途定義しておく必要があります。
```rb
# test/models/book_test.rb
class BookTest < ActiveSupport::TestCase
  set_fixture_class my_books: Book
  fixtures :my_books
  # ...
end
```
>ActiveRecord::Base.primary_key=メソッドを用いて、テーブルの主キーに使われるカラム名を上書きすることもできます。
```rb
class Book < ApplicationRecord
  self.primary_key = "book_id"
end
```
https://railsguides.jp/active_record_basics.html#:~:text=%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E5%90%8D%E3%82%92%E3%81%93%E3%81%AE%E3%82%88%E3%81%86%E3%81%AB,%3D%20%22book_id%22%0Aend

# 感想
テーブルの名前を変えられることは知らなかった。
レガシーデータベースとはなんだろうか？
チームを組んでオープンソース プロジェクトを作成する

暇な時間がたくさんあるので、もっと有意義なオープンソース プロジェクトを始めたいと思っています。企業または個人が、利益を出さずに開発するためのより良い方向性を選択することができます。自分の開発スキルだけでなく、他の人を助けることもできます。テクノロジーを持っている人であれば誰でも参加できます。また、ソフトウェアのニーズを提供することも歓迎されます。
PICTってまだあるのね

一年を振り返る Advent Calendar 2024の21日目です。

テストケースの整理がめちゃくちゃ苦手（というかアプリ設計がそもそも苦手）なので超苦労しているのですが、そういや昔PICTなるツールでテストケースざっくりピックアップできたなということで調べたところ、まだあったのでえいや。

https://github.com/microsoft/pict/releases

https://github.com/Microsoft/pict/blob/main/doc/pict.md

https://learn.microsoft.com/ja-jp/windows-hardware/drivers/taef/pict-data-source

MicrosoftのツールでCUIツールなのですが、PICT MasterとかいうExcelと組み合わせると使いやすかった印象です。これもまだあったのか。

とはいえテストケースとして不足してるケースも普通に出てくるので、PoCとかでよっぽど時間がないときとかに補助ツールとして使う感じかなと思っています。

このツールの存在は昔から知っていますが、商用環境のテストでは一回も使ったことがないのでこういうの使っていった方がよいのかわかんないです。誰か教えてください。

おわり。
AWS Vaultを使いましょう

みなさんこんにちは！株式会社グレンジでサーバーエンジニアをしている紀と申します。

最近、個人開発をしていて、短期間で異なる権限のAWSアカウントを切り替えて開発や機能検証を行う必要があるため、今回はAWS Vaultを紹介し、AWSアカウントをより便利に管理する方法について紹介します。

## AWS Vaultとは？

AWS Vaultは、AWSの認証情報を安全に管理するためのツールです。AWSアクセスキーを暗号化して保存し、ユーザーがローカル環境でAWSリソースを安全に扱えるようにします。AWS Vaultの主な目的は、AWS認証情報の管理を簡素化し、高いセキュリティを維持することです。

## 主な機能
* **安全な保存**：AWS Vaultは、macOSのKeychainやLinuxのGnome Keyringなど、オペレーティングシステムのキー管理システムを使用してAWS認証情報を保存し、安全性を確保します
* **コマンドライン統合**：AWS VaultはAWS CLIとシームレスに統合でき、ユーザーはコマンドラインから直接AWSリソースにアクセスできます
* **複数アカウントのサポート**：AWS Vaultは複数のアカウントを管理でき、ユーザーは異なるAWSアカウントに簡単に切り替えることができます


## インストールと設定
macOSでは、Homebrewを使用してAWS Vaultをインストールできます：

```
brew install aws-vault
```

## 設定

* **AWS認証情報の追加**
次のコマンドを使用してAWS認証情報を追加します
```
❯ aws-vault add <profile-name>
```
これにより、AWSアクセスキーとシークレットキーの入力を求められます

入力おわったら、AWS Vaultは自動的に認証情報をmacOSのキーチェーンに保存します。次のコマンドを使用してキーチェーン内のエントリを確認できます

* **AWS Vaultの使用**
次のコマンドを使用してAWS CLIセッションを開始します.例えば、S3バケットをリストするには：
```
❯ aws-vault exec hogo-prod
Starting subshell /bin/zsh, use `exit` to exit the subshell
❯ aws s3 ls
2024-11-08 14:04:49 hogo-alb-access-logs-027578280580
2024-11-10 20:53:23 hogo-prod-attachments
2024-11-14 08:43:41 hogo-prod-attachments-backup
```

## まとめ
以上です！
AWS Vaultは、AWS認証情報を効果的に管理し、セキュリティを強化し、複数アカウントの管理を簡素化する強力なツールです。
手軽で使えるので，皆さんも是非使ってみてください．
Code Engineに定義された権限

# はじめに
こちらの記事は下記Advent Calendar 2024で紹介しているIBM Cloud権限設定における `Code Engine` になります。

https://qiita.com/katahiro/items/274bec5ad4a9e2604dcf

# 共通権限は割愛
こちらの記事に記載しているように、プラットフォーム・アクセス、サービス・アクセスの権限でそれぞれどのようなものが共通して設定されているかを紹介させて頂きました。

https://qiita.com/katahiro/items/b5e367666fe984944d4b

こちらの記事では共通部分で出現する権限を除いた各サービス毎の権限設定を紹介します。

# Code Engineで指定可能な権限のアクセス範囲
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/335ef9ac-e939-55f3-e044-990186784a45.png)
- リソース・グループ
- Location
- Project
## リソース・グループの指定
これは指定されたリソース・グループに所属するCode Engineのみに対してアクセス権限を適用します。異なるリソース・グループのCode Engineに対しては別途権限を設定する必要があります。

## Locationの指定
これは `jp-tok`, `jp-osa` のように、Code Engineが作成されたロケーションを指定して許可を与えることが可能です。勝手に海外のDCに作成しないようにするといった対策が必要な場合は利用しても良いですね。

## Projectの指定
これは既に作成されたCode EngineのProjectが存在する場合、そのProjectを指定して権限を与えることが可能です。
開発チームには既存のProject上の操作だけ許可して、新規Projectを作らないように、といった権限の振り分けが必要な場合に利用できます。

# Code Engineに設定された権限
## プラットフォーム・アクセスの権限
※Admin : Administrator, KM : Key Manager, SCR : Service Configuration Reader
|権限|Viewer|Operator|Editor|Admin|KM|SCR|
|:---|:---:|:---:|:---:|:---:|:---:|:---:|
|codeengine.config.read||||||〇|
|codeengine.dashboard.view||〇|〇|〇|||

プラットフォーム・アクセスとして設定されているCode Engineの権限はダッシュボードの参照といった権限のみになります。Code Engineのどの機能を利用できるかはサービス・アクセス側で設定して、という感じですね。

## サービス・アクセスの権限
### Projectに対する権限
|権限|Reader|Writer|Manager|Compute Environment Administrator|
|:---|:---:|:---:|:---:|:---:|
|codeengine.computeenvironment.projects.create||〇|〇||
|codeengine.computeenvironment.projects.delete||〇|〇||
|codeengine.tenant.read|〇|〇|〇||
|codeengine.tenant.update|||〇||

プロジェクトを作成するには、WriterかManagerの権限が必要になります。
ただ、注意としてプラットフォーム・アクセスの共通権限部分でインスタンスを作成する権限が結局必要になるので、プラットフォーム・アクセスのEditor、Administratorといった権限が必要になります。
また、Code Engineはリソース・グループを明示的に指定して作成するサービスのため、`リソース・グループのみ`の権限で少なくとも対象のリソース・グループに対するReader権限が無いとインスタンスの作成で権限不足になります。

### Project内のアプリやJobに対する権限
|権限|Reader|Writer|Manager|Compute Environment Administrator|
|:---|:---:|:---:|:---:|:---:|
|codeengine.tenant.entities.read|〇|〇|〇||
|codeengine.tenant.entities.create||〇|〇||
|codeengine.tenant.entities.update||〇|〇||
|codeengine.tenant.entities.delete||〇|〇||
|codeengine.computeenvironment.create||||〇|
|codeengine.computeenvironment.delete||||〇|

プロジェクト内のアプリケーションやSecretといった構成情報のリスト表示はReader権限があれば良いですが、更新には基本的にWriter以上の権限が必要です。ただ、ProjectをIBM Cloudの他のリソースと接続する設定(codeengine.tenant.update)を行うには、Administratorの権限が必要な点に注意してください。

残念なことに執筆時点で `codeengine.computeenvironment.create/delete`がいったい何をするための権限なのかよくわかりませんでした。
この権限だけ付与してもプロジェクト上にアプリを作成したりすることもできないので、どこで利用するんだろう状態です。

# さいごに
Code Engineとして個別に設定されている権限は少なかったですね。
アプリやジョブといったコンテナ環境を立ち上げるのであれば基本的にサービスアクセスに対してWriter以上の権限を付与する必要がありそうですね。
他のリソースと接続はわざわざ宣言しなくてもそのサービスにアクセスするための認証情報を作成すれば、IBM Cloud内ネットワークでそのサービスのエンドポイントにアクセスできるはずなので、サービス・アクセスのManager権限の付与するタイミングはあまり多くは無さそうに思いました。

Compute Environment Administratorとは何者なのか…またわかったら記事を更新したいと思います。
[メモ]Windows11とUbuntu22.04でデュアルブート環境を作成する

# はじめに
仮想マシンではなくネイティブで動くUbuntuが必要になったので，メモも兼ねてPCにWindows11とUbuntu22.04の両方をインストールしてデュアルブート環境を作成する方法を書きます．
用意するものは8GB以上のUSBメモリです．

:::note warn 
注意：この記事の手順でデュアルブート環境の作成を行い，大事なデータが破損しても当方は責任を取りません．事前にしっかりバックアップを取った上自己責任で作業してください．
:::
# 環境
今回は既にWindowsがインストールされたPCに追加でUbuntuのインストールを行います．
PCの構成は次のとおりです．
- OS: Windows11
- CPU: AMD Ryzen 5 3600
- Memory: 32GB
- Storage: 1TB
- GPU: AMD Radeon rx 5600xt
# 手順
## Windowsの高速スタートアップを無効にする
設定のシステム→電源とスリープ→電源の追加設定と辿り，"高速スタートアップを有効にする（推奨）"のチェックを外します．
## Ubuntuのインストーラーを作成する
### イメージをダウンロードする
まずUbuntuのイメージを用意します．Ubuntuのホームページに日本語環境用のイメージがあるので，今回はこちらを利用します．
https://www.ubuntulinux.jp/japanese
### USBメモリにイメージを書き込む
ダウンロードしたイメージをUSBメモリに書き込みます．USBメモリにイメージを書き込むソフトは色々ありますが，今回はRaspberry Pi Imagerを使用します．
Raspberry Pi Imagerはラズパイ用のOSを書き込むときに使うソフトですが，ラズパイに限らずISOイメージをUSBメモリに書き込む用途で使用できます．UIがかなりシンプルで分かりやすいので個人的にはおすすめです．

https://www.raspberrypi.com/software/
上記のリンクからダウンロードしたらインストールして，起動します．
![スクリーンショット 2024-12-08 0.13.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3949702/3d8c500f-345e-0358-2bea-edb6dd434817.png)
起動すると画像のような画面が出ます．はじめにUSBデバイスのフォーマットを行うので，"OSを選択"から"Erase"を選択します．
次に，"ストレージを選択"から使用するUSBデバイスを選択します．
選択できたら"次へ"を押してフォーマットを行います．

フォーマットができたらISOイメージをUSBメモリに書き込みます．
"OSを選択"から"Use custom"を選択し，先ほどダウンロードしたUbuntuのISOファイルを指定します．
次に，ストレージを選択し書き込みます．このとき，カスタムの設定を使用するか？と聞かれますが，いいえを選んでください．

## インストーラーを起動する
先ほどUbuntuのイメージを書き込んだUSBメモリをパソコンに挿し，BIOSから起動順序を変更して起動します．
### インストール手順
1. そのままUbuntuのイメージが起動すると，インストーラーの画面が出てきます
画面に，"Ubuntuを試す"と"Ubuntuをインストール"が出るので，"Ubuntuをインストール"を選択します．
2. インストールの種類
UbuntuのインストーラーがWindows Boot Managerを検出してくれるので，UbuntuをWindows Boot Managerとは別にインストールを選択すると，それぞれに割り振る容量を決めるだけで自動でデュアルブートの設定になります．
(手動でパーティションの作成を行う場合はその他を選択) 
3. あとはインストールボタンを押して放置するだけです．
# まとめ
Ubuntuのインストールイメージを作成すれば，あとは画面の指示に従うだけで簡単にデュアルブート環境の作成ができます．それでは良いLinuxライフを！
UIコンポーネントライブラリに頼る理由を振り返る

この記事は [フラー株式会社 Advent Calendar 2024](https://qiita.com/advent-calendar/2024/fuller-inc) の11日目の記事です。
10日目は @furusax さんで、「[ISUCON14に出場して惜しくも優勝を逃しました（全体126位）](https://furusax0621.hatenablog.com/entry/2024/12/10/000000)」でした。

# はじめに

私の体感では、ReactでWebアプリを作るときに[Radix UI](https://www.radix-ui.com/)や [React Aria](https://react-spectrum.adobe.com/react-aria/index.html) といったUIコンポーネントライブラリの存在は欠かせないものになっています。

欠かせないものなので、新規でプロジェクトを作成する際は、必ず「どのUIコンポーネントライブラリを使うか」もセットで検討しています。

だんだんそれが当たり前になってきて、「なんでUIコンポーネントライブラリに頼るのか」を気にすることがなくなってきてしまったので、この機会に思い返してみようと思います。

# UIコンポーネントライブラリに頼る理由

考えてみた結果、大きく分けて2つくらい理由がありそうだなと考えています。
具体的には以下です。

- 実装工数を大幅に削減できる
- コンポーネントの使用方法を守ることで、アクセシビリティをある程度担保できる

これだけ書いてもよく分からないので、下でもう少し詳しく書きます。

## 実装工数を大幅に削減できる

やはりこの理由が大きいのですが、DialogやToast、Tooltipなど、作るのが大変なUIコンポーネントを簡単に扱えるようになるのは大きいです。

もしUIコンポーネントライブラリに頼ることができない場合、必要に応じて自作する必要があるので、複雑なUIコンポーネントが増えるほど、UIコンポーネントの実装工数も純増してしまいます。

そして、実装したUIコンポーネントもメンテナンスをする必要があり、UIコンポーネント起因のバグへの対処もすることになります。

結果、Webアプリのコアとなる機能の実装へ割くことができるパワーも少なくなってしまうので、よくないことばかり起きてしまいます。

UIコンポーネントライブラリを頼ることによって、これらの問題点を解消し、Webアプリの価値を高めることに注力できるのは大きなメリットだと思います。

もちろん、将来的にUIコンポーネントライブラリがメンテナンスされなくなったときに、別のUIコンポーネントライブラリを探したり、自力で代替のUIコンポーネントを自作しないといけないというリスクを背負うことにはなります。
しかし、そのリスクを鑑みても、享受できるメリットのほうが大きいと感じています。


## コンポーネントの使用方法を守ることで、アクセシビリティをある程度担保できる
今年のアクセシビリティ回りの大きなニュースとして、民間事業者の合理的配慮の義務化がありました。
参考: https://www.gov-online.go.jp/useful/article/202310/2.html#c1

これによって、アクセシビリティを確保することがより一層求められるようになってきたと考えています。

ただ実際問題として、アクセシビリティを確保するのは結構難しいです。
個人的に一番難しいのは、[ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/)に従ってアクセシブルなコンポーネントを作ることです。

アクセシブルなコンポーネントを作る関門は3つあると思っています。
具体的には以下の3つです。
- 適切なセマンティクスの提供
- キーボードナビゲーション
- フォーカス制御

ARIA Authoring Practices Guideを読むことで、上記3つをどう担保すればよいかは分かります。
しかし、それを実装に反映するには高いスキルが必要になってきます。

以上を踏まえると、UIコンポーネント側でアクセシビリティ回りの実装を担保できるのは十分なメリットだと思っています。

ただ、ここで気を付けたいのは、「実装者にアクセシビリティの知識はある程度必要である」という点です。
「コンポーネントの使用方法を守ることで」と書いてあるのはここが理由で、UIコンポーネントも使い方を間違ってしまうと、アクセシビリティを確保することができません。

例えば、Radix UIにおけるAlert Dialogコンポーネント、Dialogコンポーネントは、機能的にそんなに違いはありません。
違いは使われているロールにあり、それぞれ alertdialogロール、dialogロールが使用されています。


[MDN](https://developer.mozilla.org/ja/docs/Web/Accessibility/ARIA/Roles/alertdialog_role)には
> 通常のダイアログとの違いは、alertdialog ロールはアラート、エラー、またはワーニングが発生した場合にのみ使用するべきであることです。 言い換えれば、ダイアログの情報とコントロールがユーザーの即時の注意を必要とするとき、dialog の代わりに alertdialog が使用されるべきです。 この区別をするのは開発者次第です。

とあり、alertdialogロール、dialogロールの意味に違いのあることが分かります。

もし実装者がこのことを知らずにAlert Dialogコンポーネント、Dialogコンポーネントの使い分けを行うと、支援技術に適切な意味が伝わらず、読み上げソフトを使用しているユーザーが混乱してしまう原因になってしまう恐れがあります。

以上から、UIコンポーネントライブラリの使い方もある程度気を付ける必要があると思っています。
大抵UIコンポーネントライブラリのドキュメントに、準拠するデザインパターンへのリンクがあるので、そこを参照しながら知識をつけていけるとよいかな......?と思っています。


# おわりに
自分なりにUIコンポーネントライブラリに頼る理由を言語化してみました。

こういうことを明確にしておくと、何か判断を行うときの重要な指針になったりするので、今後も定期的に振り返っていきたいなと思っています。

明日は @Mgtantheta さんで 「【Android】Navigation ComposeのSafe Argsについて(フォルダの分け方など)」です!
Power BIって何？

---
author: daruma
tags: Power BI, ビジネスインテリジェンス, 初心者
---

# はじめに

◆この記事は何？  
Power BIについての記事

◆対象は？  
聞いたことあるんだけど、具体的なイメージがわからない

◆この記事のねらい  
目的と概念的なお話をより、深堀りさせるきっかけにしてもらえたらというのが狙いです。

BI（ビジネスインテリジェンス）とは、企業や組織が持つ膨大なデータを収集、分析、可視化し、経営や業務の意思決定に役立てるためのツールやシステムのことです。BIツールを使用することで、データを基にした迅速かつ正確な意思決定が可能になります。

## 有名なBIツール

以下は、特に有名なBIツールの一部です：
- **Microsoft Power BI**: Microsoft製のBIツールで、Excelとの連携が強力です  
  [Microsoft Power BI](https://www.microsoft.com/ja-jp/power-platform/products/power-bi)
- **Tableau**: データの可視化に優れたツールで、直感的な操作が可能です  
  [Tableau](https://www.tableau.com/)
- **Qlik Sense**: データの探索と可視化に特化したツールで、ユーザーが自由にデータを操作できます  
  [Qlik Sense](https://www.cdata.com/jp/kb/tech/ssas-connect-qlikcloud.rst?msclkid=c95cd6fa10dd11ab6528b1af99462b73)
- **Looker**: Google Cloudが提供するBIツールで、データの統合と分析が容易です  
  [Google Looker Studio](https://www.techfirm.co.jp/blog/looker-studio)
- **Domo**: クラウドベースのBIプラットフォームで、リアルタイムのデータ可視化と分析が可能です  
  [Domo](https://www.domo.com/)

これらのツールは、それぞれ異なる特徴と強みを持っており、企業のニーズに応じて選択されます。BIツールを導入することで、データに基づいた戦略的な意思決定が可能になり、業務効率の向上や競争力の強化に繋がります。

# Power BIとは？

Power BIは、**Microsoftが提供するビジネスインテリジェンスツール**です。データを収集、統合、視覚化し、インサイトを抽出するためのツールです。

## Power BIの主な機能

- **データの統合**: 多様なデータソースからデータを取り込みます
- **データの視覚化**: データをグラフやダッシュボードとして視覚化します
- **インサイトの抽出**: データを分析し、ビジネスインサイトを得ることができます

※ビジネスインサイトとは  
企業が意思決定や戦略策定に役立てるための深い洞察や知識のことです。顧客の行動パターンや競合他社の動向、業界のトレンドなどを理解し、それを基にした戦略を立てることができます。

## Power BIの競合ツール

- [Tableau](https://www.tableau.com/)
- [Qlik Sense](https://www.cdata.com/jp/kb/tech/ssas-connect-qlikcloud.rst?msclkid=c95cd6fa10dd11ab6528b1af99462b73)
- [Looker](https://www.techfirm.co.jp/blog/looker-studio)
- [Domo](https://www.domo.com/)

# Power BI vs Tableau: どっちがいいの？

## 比較表

| 項目               | Power BI                                                                 | Tableau                                                                 |
|--------------------|--------------------------------------------------------------------------|-------------------------------------------------------------------------|
| **価格**           | 無料版あり。Power BI Pro（月額約10ドル）、Power BI Premium（企業向け） | 無料版あり（Tableau Public）。Tableau Creator（月額約70ドル）          |
| **ユーザーインターフェース** | 直感的な操作。Excelに似たインターフェースで使いやすい                | ビジュアル重視。ドラッグ＆ドロップで直感的に操作可能                    |
| **データ接続**     | 多様なデータソースに接続可能。リアルタイムデータ更新も対応                | 豊富なデータ接続。ライブ接続と抽出が可能                                |
| **データ可視化**   | 多くの標準ビジュアルとカスタムビジュアルを追加可能                        | 高度なビジュアル作成が可能。インタラクティブなダッシュボードを作成可能 |
| **学習曲線**       | 簡単に始められる。豊富なオンラインリソースが利用可能                    | 初心者には少し難しいが、慣れると強力。大規模なユーザーコミュニティあり |

## まとめ
どちらのツールも優れたBIツールだけど、使い方や目的によって選ぶといいよ。Microsoft製品に慣れているならPower BI、データの可視化にこだわりたいならTableauがおすすめ。どちらも試してみて、自分に合ったツールを見つけてね！

## おわりに

この記事では、Power BIについて概要を説明しました。理解の一助になれば幸いです。以前はTableauを使用していましたが、最近知り合った情シスの方の影響もあり、Power BIについても情報収集を進めていこうと思っています。
PyTorch3dにおける、libcudart.so.10.1: cannot open shared object file: No such file or directoryの解決備忘録

# はじめに
pytorchをgithubからインストールすることに成功したものの、実行する際、以下のエラーが出てしまいました。この解決策を備忘録として残します。
(原因はよくわかっていません)

```console
$ python test.py
ImportError: libcudart.so.10.1: cannot open shared object file: No such file or directory
```
# 問題
私の環境(変更前)は以下です。
- cuda 11.1
- Python : 3.8
- torch : 1.9.1 (cu111)
- pytorch3d : 0.3.0

※pytorch3dは以下のコマンドでインストールしました
```console
pip install git+https://github.com/facebookresearch/pytorch3d.git
```
cuda11.xを使用しているため、libcudart.so.10.1が見つからないようです。[公式サイト](https://github.com/facebookresearch/pytorch3d/blob/main/INSTALL.md)より、cudaとtorchのバージョンに対応するものwheelファイルからインストールを試みましたが、同様のエラー。
```console
pip install pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/py38_cu111_pyt191/index.html
```

# 解決方法
こちらでは、torchのバージョンによって未対応と言及されています。

https://github.com/facebookresearch/pytorch3d/issues/688

torch1.9.xを使用する必要がどうしてもあったため、試しにtorch1.9.0(cu111)に変更し、pytorch3dを再インストールしたところ、無事動作しました。

環境(変更後)
- cuda 11.1
- Python : 3.8
- torch : 1.9.0 (cu111)
- pytorch3d : 0.7.8

# おわりに
今回は、PyTorch3dを使用したコードを実行する際に生じるエラーの解決策を書きました。
torchのバージョンを1.9.1から1.9.0へダウングレードすることで、無事動作しましたが、原因はよくわかっていません。

torchとpytorch3dの対応表や、他の解決法があれば、ご教授いただければ幸いです。
# 参考
π(パイ)よりτ(タウ)の方がいいよねって話

数学でよく出てくる**π（パイ）**。しかし最近、「いや、 **τ（タウ）** の方がいいんじゃないか？」という議論が数学好きの間で盛り上がっています。

この記事では、**πとτの違い**や、なぜτが「いい」とされるのかを簡潔にまとめてみます。

---

## πとτの定義

まずは、**π**と**τ**の定義をおさらいしましょう。

### π（パイ）

πは、円周を直径で割った比率として定義されます。

$$
\pi = \frac{\text{円周}}{\text{直径}}
$$

その値は、よく知られている通り

$$
\pi \approx 3.14159
$$

です。

### τ（タウ）

一方で、τは「円周を半径で割った比率」として定義されます。

$$
\tau = \frac{\text{円周}}{\text{半径}} = 2\pi
$$

その値は

$$
\tau \approx 6.28318
$$

となります。

---

## なぜτの方がいいのか？

「πじゃダメなんですか？」と思うかもしれませんが、実は数学的にも教育的にもτの方が有利な点がいくつかあります。

---

### 1. 円と角度の対応が自然になる

円周の長さや角度を考えるとき、ラジアンという単位を使います。このラジアンは「円周の何割か」を表す単位なので、1周を「τ」とする方が直感的です。

#### 現在（πを使用）

$$
90^\circ = \frac{\pi}{2}
$$

$$
180^\circ = \pi
$$

$$
360^\circ = 2\pi
$$

#### τを使った場合

$$
90^\circ = \frac{\tau}{4}
$$

$$
180^\circ = \frac{\tau}{2}
$$

$$
360^\circ = \tau
$$

1周が「τ」となることで、角度とラジアンの対応がシンプルになります。

---

### 2. 数学の公式もより直感的になる

円の面積公式は通常、以下のように**π**を使って表されます：

$$
A = \pi r^2
$$

これを**τ**に置き換えると、次のように書き換えられます：

$$
A = \frac{\tau r^2}{2}
$$

---

#### なぜこの形が直感的？

この形は「**円周を基準にした面積**」として解釈できるため、式の意味がより直感的になります。

---

### 3. 物理公式がスッキリする

物理や工学では、2π が頻繁に登場します。これを**τ**に置き換えると、式が簡潔になります。

#### 例：フーリエ変換

現在、フーリエ変換では次のような公式を使います：

$$
e^{2\pi i} = 1
$$

これをτに置き換えると、

$$
e^{\tau i} = 1
$$

となり、式がスッキリします。

---

### 3. あの有名な e^iπ + 1 = 0もさらに美しくなる

オイラーの公式は、数学の中でも最も美しい式の一つと言われています：

$$
e^{i\pi} + 1 = 0
$$

この式は、円周率 (π) を使って複素数の単位円を表現しています。しかし、τ を使うと、この公式がさらに直感的かつ簡潔になります。

---

#### オイラーの公式の τ バージョン

まず、オイラーの公式を一般形で書くと次のようになります：

$$
e^{i\theta} = \cos\theta + i\sin\theta
$$

ここで、θ = τ を代入すると：

$$
e^{i\tau} = \cos\tau + i\sin\tau
$$

---

#### なぜこれが美しい？

従来のオイラーの公式では、1周（2π）を使って次のように表されていました：

$$
e^{i 2\pi} = 1
$$

しかし、τ を使うと1周が「τ」そのものとして表現でき、式がよりシンプルで美しくなります：

$$
e^{i\tau} = 1
$$

---

### 結論

τ を使うことで、オイラーの公式も「1周が τ」という直感的な定義に基づいてより美しくなります。

- 従来の形：
  $$
  e^{i 2\pi} = 1
  $$
  $$
  e^{i \pi} + 1 = 0
  $$


- τを使った形：
  $$
  e^{i\tau} = 1
  $$

---

## 結論：τは未来のスタンダード
πとτ、どちらが良いかは用途や文脈によりますが、τの方が直感的で式がスッキリするケースが多いのは事実です。

とはいえ、数学界や教育の現場では長年πが使われてきたため、すぐにτが主流になるわけではないでしょう。でも、τを使った方が「理解が早い」「計算が楽しい」と感じる場面があるなら、ぜひ試してみてください！
名前空間付きモデルを作成する

# モデルに名前空間をつけて区別できる
>デフォルトのActive Recordモデルは、app/modelsディレクトリの下に配置されます。ただし、`互いによく似たいくつかのモデルを独自のフォルダと名前空間の下にまとめて配置して、モデルを整理することも可能`です。たとえば、app/models/bookディレクトリの下にorder.rbファイルとreview.rbファイルを置いて、それぞれ`Book::Order`と`Book::Review`という`名前空間付きのクラス名を付ける`というように、Active Recordでは`名前空間モデルを作成`できます。

https://railsguides.jp/active_record_basics.html#:~:text=%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%AEActive%20Record%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AF%E3%80%81app/models%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%AE%E4%B8%8B%E3%81%AB%E9%85%8D%E7%BD%AE%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82%E3%81%9F%E3%81%A0%E3%81%97%E3%80%81%E4%BA%92%E3%81%84%E3%81%AB%E3%82%88%E3%81%8F%E4%BC%BC%E3%81%9F%E3%81%84%E3%81%8F%E3%81%A4%E3%81%8B%E3%81%AE%E3%83%A2%E3%83%87%E3%83%AB%E3%82%92%E7%8B%AC%E8%87%AA%E3%81%AE%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E3%81%A8%E5%90%8D%E5%89%8D%E7%A9%BA%E9%96%93%E3%81%AE%E4%B8%8B%E3%81%AB%E3%81%BE%E3%81%A8%E3%82%81%E3%81%A6%E9%85%8D%E7%BD%AE%E3%81%97%E3%81%A6%E3%80%81%E3%83%A2%E3%83%87%E3%83%AB%E3%82%92%E6%95%B4%E7%90%86%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%82%82%E5%8F%AF%E8%83%BD%E3%81%A7%E3%81%99%E3%80%82%E3%81%9F%E3%81%A8%E3%81%88%E3%81%B0%E3%80%81app/models/book%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%AE%E4%B8%8B%E3%81%ABorder.rb%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%A8review.rb%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E7%BD%AE%E3%81%84%E3%81%A6%E3%80%81%E3%81%9D%E3%82%8C%E3%81%9E%E3%82%8CBook%3A%3AOrder%E3%81%A8Book%3A%3AReview%E3%81%A8%E3%81%84%E3%81%86%E5%90%8D%E5%89%8D%E7%A9%BA%E9%96%93%E4%BB%98%E3%81%8D%E3%81%AE%E3%82%AF%E3%83%A9%E3%82%B9%E5%90%8D%E3%82%92%E4%BB%98%E3%81%91%E3%82%8B%E3%81%A8%E3%81%84%E3%81%86%E3%82%88%E3%81%86%E3%81%AB%E3%80%81Active%20Record%E3%81%A7%E3%81%AF%E5%90%8D%E5%89%8D%E7%A9%BA%E9%96%93%E3%83%A2%E3%83%87%E3%83%AB%E3%82%92%E4%BD%9C%E6%88%90%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82

```rb
***********@********** % bin/rails generate model Book::Order
      invoke  active_record
      create    db/migrate/20241210150333_create_book_orders.rb
      create    app/models/book/order.rb
    conflict    app/models/book.rb
  Overwrite /**************/app/models/book.rb? (enter "h" for help) [Ynaqdhm] n
        skip    app/models/book.rb
```
>別の可能性として、app/modelsディレクトリの下に既にBookモデルが存在しており、このモデルを上書きしたくない場合は、プロンプトでnを選択すれば、generateコマンドでbook.rbを上書きしなくなります。 この場合は
```rb
***********@********** % bin/rails d model Book::Order
      invoke  active_record
      remove    db/migrate/20241210150333_create_book_orders.rb
      remove    app/models/book/order.rb
```

#　感想
名前空間を使ったモデルはどう言うときに使うのだろうか？
【ZABBIX7.0LTS】アラートメール送信が遅延した件（備忘録）

# 【事象】
Zabbix のアラートトリガー設定で、障害発生時にメールが送信されるように設定していた。しかし、障害発生時刻とメール受信時刻に5～10分程度の遅れが生じることがあり、さらに一部の障害メールが未受信となるケースも確認された。

# 【調査】
以下の確認およびパラメータ調整を行ったが、問題は改善されず。

・SMTPサーバのログ確認
　　→ 特にエラーは記録されていない。

・"Template App Zabbix Server" を使用した確認
　　→ Zabbixプロセスおよびキュー状態を確認したところ、一部でリソース不足が発生して
　　　いた。そのためパラメータを調整し、リソース不足を解消したが問題は解決せず。

・障害検知時のイベント詳細確認（検知後の動作）
　　→ 障害検知後のメール送信およびパトランプ点灯処理の発動が明らかに遅れていた。

※ 当時 Zabbix をデバッグモードに設定してログを確認する対応は実施できておらず。
　 やり方が分からなかった。（誰か教えてください・・。）


# 【原因・結果】
Zabbix のアラートトリガー設定で、障害時に「メール送信」と「パトランプ点灯」が実行されるように設定していた。しかし、パトランプ（例: 警子ちゃん）が未設置の状態だったため、毎回エラーが発生し、「パトランプ点灯」処理が失敗していた。そこで試しにアラートトリガー設定で「パトランプ点灯」を無効化したところ、メール遅延が解消された。どうやら原因は、「パトランプ点灯」処理の失敗によりイベント処理が滞留していたことのようです。パトランプを設置後、アラートトリガー設定で「メール送信」と「パトランプ点灯」の両方を有効にしても、メール遅延は発生しなかった。

# 備考
・[【ZABBIX 7.2 Documentation】1. Problems](https://www.zabbix.com/documentation/current/en/manual/web_interface/frontend_sections/monitoring/problems)
・[zabbix のアラートが飛ばない時のチェックリスト](https://zenn.dev/yakumo/articles/ffc47d35b922464fae89fb4a4e06f887)
・[Zabbixトラブルシューティング -Zabbix Serverログの見方](https://qiita.com/ike_dai/items/665ca45c70dbdf728cb4)
・[Zabbix Enterprise カスタマーポータル](https://enterprise.zabbix.co.jp/kbcategory/troubleshoot/page/2)
・[Zabbixのパフォーマンス&トラブルシューティングTips](https://assets.zabbix.com/img/zabconf2019_jp/presentations/08_zabconf2019.pdf)
Amazon Polly で音声をコントロールする

先日、友人に音声読み上げを相談されたので調査。

テキストから音声を生成するAIはたくさんあるが、細かいコントロールができない。

Amazon Polly はできそうだったので、基本的な使い方を調査しました。

# Amazon Polly とは
テキストを肉声に近い音声に変換するクラウドサービスです。

# 無料利用枠
最初の12ヶ月間、標準音声で500万文字、ニューラルボイスで100万文字、長文形式音声で50万文字、ジェネレーティブボイスで10万文字が利用できます。
詳しくは[こちら](https://aws.amazon.com/jp/polly/pricing/?nc=sn&loc=4)

# 今回の利用目的
飲食店を経営している友人なので、「大繁盛店！」など、明るく抑揚をつけた音声が欲しいらしい。

# 使ってみる
まずはサービスサイトにアクセス。

![スクリーンショット 2024-12-10 22.31.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/022d68bf-ea3e-d89c-7ea6-c6de8260176f.png)

「Pollyを試す」でサービスのコンソール画面に入ります。（AWSアカウントがある前提）

![スクリーンショット 2024-12-10 22.32.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/d9891470-ba48-27cd-1f57-f71486d2682f.png)

ニューラルとスタンダードがあります。
二つの音声を比べてみましょう。

まずは「ニューラル」の「Kazuha」さん
[Kazuha_mp3](https://nayzach.com/mp3/speech_20241210133301601.mp3)

続いて、「スタンダード」の「Mizuki」さん
[Mizuki_mp3](https://nayzach.com/mp3/speech_20241210140751345.mp3)

ニューラルの方が良さそうですね。
このまま「ニューラル」の「Kazuha」さんで進めます。

### 1. テキストをそのまま読ませてみる
「大繁盛店！」を4パターンで読ませてみました。音声は[こちら](https://nayzach.com/mp3/speech_20241210141910618.mp3)。

![スクリーンショット 2024-12-10 23.18.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/fc865162-594d-183c-35f7-1c6ec16d72dd.png)

以下の2パターンが良さそうですね。
- 大繁盛店！
- だい はん じょう てん！

### 2. SSML（Speech Synthesis Markup Language）を使ってみる
それでは、ここからさらにコントロールしてみましょう。
画面右側に「SSML」があるので、これをONにします。

SSMLは「Speech Synthesis Markup Language」の略で、これを使用すると、音声の選択、単語の発音の変更、休止の追加など、音声出力を変更できるそうです。（[ドキュメント](https://docs.aws.amazon.com/polly/latest/dg/ssml.html)）

ドキュメントをざっくり読んで、調整してみました！
音声は[こちら](https://nayzach.com/mp3/speech_20241210145513000.mp3)

![スクリーンショット 2024-12-10 23.57.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/25d28c4a-9de9-18c1-3f71-d7d55f1dcfb3.png)

今回の入力テキスト
```text
<speak>
大繁盛店！
立川、居酒屋
<prosody rate="110%">
<sub alias="かい ぞく">家偉族</sub>の、<prosody volume="x-loud" rate="120%" >スペシャル コー ス！</prosody>
</prosody>
</speak>
```
今回やってみた調整方法は、以下の通り。
- prosodyタグのrate属性で音声の速度を調整
- 感嘆符や句読点で強調や間を調整
- subのalias属性で読み方を固定
- aliasの文字列にスペースを入れて、イントネーションを微調整
- prosodyのvolume属性で音量を調整

# まとめ
今回は、Amazon Pollyにおける音声のコントロール方法を検証しました。
まだまだ改良の余地がありますが、可能性は見えたと思います。
C0とかMCCとか

一年を振り返る Advent Calendar 2024の20日目です。

テストカバレッジの話をベンダーさんとしたときにc0とかc1っていう単語を使って話していたのですが、

まさかの聞いたことないと言われて驚きだったので記事にしてみます。

と言いつつ以下の記事にまとまっているので引用させてもらいます。

https://tech.nri-net.com/entry/coverage_c0_c1_c2_mcc

C0：命令網羅（ステートメント・カバレッジ）
C1：分岐網羅（ブランチ・カバレッジ）
C2：条件網羅（コンディション・カバレッジ）
MCC：複合条件網羅（マルチコンディション・カバレッジ）

命令網羅とか分岐網羅とかいう単語は結構知ってると思いますが、C1とかC2とかとか、こういった単語でやりとりする世界線もあるということで知ってて損はないというブログでした。終わり。
3Dセキュアについて調べてみた / I looked into 3D Secure (日本語 / 英語)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812041/c719ef63-f342-b32d-8a05-36167503eecc.png)
# 日本語
こんばんわ！
Advent Calendar 2024に参加してまして、4日目の記事を書いていこうと思います。
題材は「決済を実装した体験談や決済サービス（クレカ、QRコード、何でもOK！）の情報を投稿しよう！ by PAY Advent Calendar 2024」ということで、3Dセキュアについて調べていこうと思います！

### 3Dセキュア (3D Secure) とは？
3Dセキュアは、オンラインショッピングにおけるクレジットカード取引を安全に行うための追加認証サービスです。これにより、不正利用のリスクを軽減し、購入者と販売者の双方に安心感を提供します。

### 3Dセキュアの仕組み
3Dセキュアは、カード発行会社、加盟店、カード所有者の間でデータを安全にやり取りするための仕組みで、「3D」とは以下の3つのドメイン (領域) を指します：

#### イシュアードメイン (Issuer Domain)

クレジットカードを発行した銀行やカード会社の領域。

#### アクワイアードメイン (Acquirer Domain)

加盟店が利用している決済プロバイダーの領域。

#### インターオペラビリティドメイン (Interoperability Domain)

VisaやMastercardなど、カードブランドが提供するネットワークの領域。

### 3Dセキュアの主な特徴
追加認証ステップ 購入時に、カード情報の入力だけでなく、購入者本人であることを証明するための追加ステップが求められます。

ワンタイムパスワード (OTP) の入力

生体認証 (指紋や顔認証)

専用アプリでの承認

#### 本人確認の強化 
これにより、カード情報を盗んだ第三者が勝手に使うのを防ぎます。特に、従来の静的なパスワードよりも安全性が高い動的な認証が主流です。

#### 責任分担の変更

3Dセキュアが有効な取引では、不正取引が発生した場合の責任がカード会社から加盟店へ移る場合があります。この仕組みは「チャージバック保証」と呼ばれます。

# ENGLISH
Good evening!
I'm participating in Advent Calendar 2024 and I'm going to write an article for day 4.
The subject is “Let's post our experiences of implementing payments and information about payment services (credit cards, QR codes, whatever!)! by PAY Advent Calendar 2024”, I will be looking into 3D Secure!

### What is 3D Secure (3D Secure)?
3D Secure is an additional authentication service to secure credit card transactions for online shopping. This reduces the risk of fraudulent use and provides peace of mind to both the buyer and seller.

### How 3D Secure works
3D Secure is a mechanism for the secure exchange of data between card issuers, merchants, and cardholders. “3D” refers to the following three domains (areas)

#### Issuer Domain

The domain of the bank or credit card company that issued the credit card.

#### Acquirer Domain

The domain of the payment provider used by the merchant.

#### Interoperability Domain

The domain of the networks provided by card brands such as Visa and Mastercard.

### Key Features of 3D Secure
Additional Authentication Steps When making a purchase, in addition to entering the card information, an additional step is required to prove the identity of the purchaser.

One-time password (OTP) entry

Biometric authentication (fingerprint or face recognition)

Authorization via a dedicated app

#### Enhanced identity verification 
This prevents a third party from stealing the card information and using it without permission. In particular, dynamic authentication is more secure than traditional static passwords.

#### Change in Responsibility Assignment

For transactions where 3D Secure is enabled, responsibility for fraudulent transactions may be shifted from the card company to the merchant. This mechanism is known as “chargeback guarantee.
データベース設計 正規化と非正規化のバランス

## はじめに

今回は、正規化による更新異常排除の効果や、正規化が不都合を招くケース、そして非正規化による履歴保持や処理高速化について整理します。

## 本文

### 正規化による不都合と非正規化

正規化は、データの冗長性や更新異常（挿入・更新・削除時の不整合発生）を防ぐために行います。一般的には最新・整合性のあるデータを確実に扱うために有効です。しかし、最新化が逆に不都合を招くケースもあります。

#### 履歴や古い情報保持のニーズ

**ケース1**: 履歴を残す必要がある場合  
たとえば、顧客マスタは常に最新情報を更新しますが、「過去に顧客がどんな登録情報だったか」という履歴を残したい場合、単純な正規化モデルでは不便です。

**サンプル：顧客履歴テーブル**  
顧客履歴(顧客コード, 顧客名, 適用開始日, 適用終了日, 変更連番)

|顧客コード|顧客名       |適用開始日      |適用終了日     |変更連番|
|---------|------------|-------------|-------------|------|
|C001     |田中一郎     |2024-01-01   |2024-06-30   |1     |
|C001     |田中一郎(改) |2024-07-01   |NULL         |2     |

ここで、`NULL`の適用終了日は最新データを意味します。正規化された1顧客1行構造では過去データが消えてしまいますが、履歴保持用のテーブルを用意することで過去の状態も参照可能です。

**ケース2**: 売上伝票や受注情報の履歴保持  
売上発生時点の単価や商品名を残すには、`伝票明細`テーブルに価格や商品名をコピーしておく非正規化が有効です。

**サンプル：伝票明細テーブル**  
伝票明細(伝票番号, 商品コード, 商品名, 単価, 数量)

|伝票番号|商品コード|商品名 |単価|数量|
|-------|--------|-----|---|---|
|1001   |P001    |りんご|120|10 |
|1001   |P002    |みかん|100|5  |

このように、`商品`テーブルは常に最新単価を持つ一方、`伝票明細`には取引時点の単価・商品名を持たせることで履歴を確保します。

### 処理高速化のための非正規化

正規化を行うとテーブルが増え、データ取得時に多くの結合が必要になります。これがパフォーマンス低下を招く場合、あえて非正規化して高速化を図ることがあります。

#### 1. 導出属性を持たせる

集計結果や累計額などは、SQLで毎回計算すると負荷が高まります。事前に計算結果を属性として保持しておく方法があります。

**サンプル：累計購入額を保持した顧客テーブル**  
顧客(顧客コード, 顧客名, 購入累計額)

|顧客コード|顧客名   |購入累計額|
|--------|--------|-------|
|C001    |田中一郎 |50000  |
|C002    |鈴木花子 |32000  |

ここで`購入累計額`は本来別テーブルから集計できますが、計算済みで保持することで検索を高速化します。変更時にはトリガーやアプリケーション側ロジックで累計額を更新し、整合性を維持します。

#### 2. 属性を重複して持たせる

よく参照される値（例：マイレージ倍率など）を別テーブル参照ではなく、顧客テーブル側にも持たせることで結合回数を減らし、高速化を図ります。

**サンプル：マイレージ倍率を重複保持**  
マイレージサービス(累計下限額, マイレージ倍率)

|購入累計下限額|マイレージ倍率|
|----------|-----------|
|20000     |1.2         |
|50000     |1.5         |

顧客(顧客コード, 顧客名, 購入累計額, マイレージ倍率)

|顧客コード|顧客名   |購入累計額|マイレージ倍率|
|--------|--------|-------|---------|
|C001    |田中一郎 |50000  |1.5      |
|C002    |鈴木花子 |32000  |1.2      |

変更時にはマイレージ倍率をトリガーやストアドプロシージャなどで再計算し、顧客テーブルを更新する必要がありますが、検索時の結合が不要になり高速化が可能です。

#### 3. テーブルを1つにまとめる

複数テーブルに正規化している場合でも、アクセス頻度が高く結合コストが問題なら、一部非正規化して1テーブルに集約することもあります。  
ただし、極端な非正規化は更新異常のリスクを増やすため、必要最小限の範囲で留めることが重要です。更新漏れを防ぐための定期的な整合性チェックを行うバッチ処理を導入するといった方法が考えられます。

## まとめ

正規化はデータの整合性・更新異常防止に効果的ですが、実務では履歴保持や高速化ニーズにより非正規化を検討する場面も多くあります。履歴確保用テーブルや、導出属性・重複属性を持たせる、テーブルをまとめるといった手法で、パフォーマンスや業務要件に応じた柔軟なデータ設計が可能です。