OmniAICreator/Qiita-1.07M huggingface dataset:
Cognos Analytics レポートでの数値データのプラス・マイナス記号表示

# 概要
数値データの+/- 表示を以下のように指定する場合のやり方です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/6540cd86-fb57-fa63-8ece-5a4e22178d8d.png)

参考資料はこちらになりますが、この記事の手順だけだと設定が足りないので、補足しつつ手順をご紹介します。
**How to display numeric sign for positive and negative values**
https://www.ibm.com/support/pages/how-display-numeric-sign-positive-and-negative-values

# 実装手順
以下のデータを例にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/3c7761f0-26eb-1839-b354-3a19dabe77d0.png)

対象のリスト列の本体のプロパティから「データ形式」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/8e9f1510-7137-777c-b460-d083fa76e07e.png)

記事にある通り、パターンで「+#」、値が負の場合の書式で「-#」を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/a10d0f50-e5f4-8c5b-55fb-58c388581955.png)

この表示になります。「+0」はイマイチなので「0」にしたいですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/346d14f4-51d2-843a-f492-3ce30caf9c1b.png)

再度データ形式で「ゼロの場合に表示する文字」を「0」に指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/42d1e2fc-9150-a035-8f3c-92f0a81ecd28.png)

良い感じですが、3桁ごとの「,」区切りがいつの間にか消えてますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/766123ec-8c88-1245-c935-1782a2966bde.png)

パターンと値が負の場合の書式を以下のように指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/3765dfa0-805a-7c5d-d577-c89f6808ad50.png)

完成です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/f10de0b1-1574-ecd9-a189-a62e46be748f.png)
Hexabase TypeScript SDKを使ってプロジェクトをCRUD操作する

[Hexabase（ヘキサベース）](https://www.hexabase.com/)は企業においても安心して利用できるBaaS（Backend as a Service）を提供しています。多くのBaaSがそうであるように、主にフロントエンド開発者に利用してもらいたいと考えています。そこで現在、TypeScript SDKの開発が進められています。

この記事ではHexabase TypeScript SDKのインストールと、プロジェクトのCRUD操作について紹介します。

## インストール

インストールはnpmやyarnを使って行います。

```
# npmの場合
npm install @hexabase/hexabase-js

# yarnの場合
yarn add @hexabase/hexabase-js
```

## インポート

インポートすると、 `HexabaseClient` というオブジェクトが取得できます。

```jsx
import { HexabaseClient } from "@hexabase/hexabase-js";
```

## 初期化

HexabaseClientを初期化します。

```jsx
const client = new HexabaseClient();
```

### 認証

Hexabaseでは業務利用を想定しているため、利用する際に認証情報が必須になります。最初はメールアドレスとパスワードで認証し、その後はトークンを使ってGraphQLにアクセスします。 `client` を使って処理します。

初回の認証は次のようになります。emailとパスワード、またはトークンが必須です。

```jsx
await client.login({email, password, token});
```

後はこの `client` に対して処理を行います。

## 現在のワークスペースを取得する

ログインした時点でHexabaseClientのcurrentWorkspaceが現在のワークスペースオブジェクトになっています。

```jsx
client.currentWorkspace
```

ワークスペースを切り替える場合には、 `setWorkspace` メソッドを使います。

```jsx
client.setWorkspace(newWorkspaceId);
```

## すべてのプロジェクトを取得する

プロジェクトはワークスペース以下に紐付く形で定義されています。すべてのプロジェクトを取得する場合には、ワークスペースの `projects` メソッドを呼びます。

```jsx
const workspace = client.currentWorkspace!;
const projects = await workspace.projects();
```

## プロジェクトと紐付いたデータストアを取得する

ワークスペースに紐付いたプロジェクトとともにデータストアも一緒に取得するためのメソッド `projectsAndDatastores` もあります。

```jsx
const workspace = client.currentWorkspace!;
const { projects, datastores } = await workspace.projectsAndDatastores();
```

## プロジェクト作成時のテンプレートを取得する

プロジェクトを作成する際には、テンプレート（ガントチャートなど）を指定可能です。これは独自に作成することもできるので、共通した定義のプロジェクトを作成しておいて、テンプレートとして使い回せます。

```jsx
const workspace = client.currentWorkspace!;
const templates = await workspace.projectTemplates();
```

## プロジェクトを作成する

プロジェクトを作成する際には、名前を指定します。日英を指定できます。

```jsx
const workspace = client.currentWorkspace!;
const project = await workspace.project();
project
  .set('name', {
    ja: '新しいプロジェクト',
    en: 'new project'
  })
  .set('template_id', templates[0].id); // テンプレートを指定する場合
await project.save();
```

## プロジェクトの詳細を取得する

プロジェクト（に限らずデータストアなども）の詳細情報を取得する際には `getDetail` メソッドを用意しています。

```jsx
const workspace = client.currentWorkspace!;
const projects = await workspace.projects();
const project = projects[0];
// 以下でも可能
// const project = workspace.project(projectId);
// 詳細取得
await project.getDetail();
```

## プロジェクトを更新する

プロジェクトの名前やテーマ（管理画面の配色）を変更できます。

```jsx
project
  .set('name', {
    en: 'test update',
    ja: 'test update',
  })
  .set('theme', 'blue');
await project.save();
```

## プロジェクトを削除する

プロジェクトを削除する際は `delete` メソッドを使います。

```jsx
const res = await project.delete();
```

## まとめ

プロジェクトは下にデータストアやレポートなどが紐付き、アプリケーション開発する際には最も使う部分になります。

Hexabase TypeScript SDKを使えば、VueやReactなどと連携したWebアプリを素早く開発できるようになります。2023年04月現在絶賛開発を進めていますので、ぜひ試していただいてフィードバックいただければ嬉しいです！

[hexabase/hexabase-js](https://github.com/hexabase/hexabase-js)
enebularでnode-red その14

# 概要
enebularでnode-redやってみる。
スクレイピングのテストするサーバーが欲しかったので、作ってみた。

# フロー


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/10300d05-f03d-327a-5cbb-87d0deeecac8.png)

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/d0df055c-4784-3e89-6899-32ac7a4e5314.png)

以上。
BigQueryをTerraformで作成する時につまずいたポイント

## やりたいこと
BigQueryでCSVファイルをアップロードしたり、Google Spread Sheetを参照してテーブルを作成することはよくありますよね？そして作成したテーブルに対してレコードをappendしたりします。

そこで、Terraformでリソースを作成する際に色々躓いたのでここに記載します。


## 結論
google_bigquery_jobを使用して、予め作成しておいたネイティブテーブルにデータをロードさせます。外部テーブルとして作成してしまうとデータを流すことができませんのでご注意ください。
```yaml
resource "google_bigquery_dataset" "default" {
  dataset_id                  = "foo"
  friendly_name               = "test"
  description                 = "This is a test description"
  location                    = "EU"
  default_table_expiration_ms = 3600000

  labels = {
    env = "default"
  }
}

resource "google_bigquery_table" "default" {
  dataset_id = google_bigquery_dataset.default.dataset_id
  table_id   = "bar"
}

resource "google_bigquery_job" "job" {
  job_id     = "job_query"

  load {
    destination_table {
      project_id = google_bigquery_table.default.project
      dataset_id = google_bigquery_table.default.dataset_id
      table_id   = google_bigquery_table.default.table_id
    }

    source_uris = ["gs://${google_storage_bucket.~}"]

    source_format         = "CSV"
    skip_leading_rows     = 1
    allow_quoted_newlines = true
    field_delimiter       = ","
    quote                 = "\""
    autodetect            = true
    write_disposition = "WRITE_TRUNCATE"
  }
}
```


## 問題
ドキュメントにあるようなexternal_data_configurationといったコードを使用すると外部テーブルとして作成してしまうので、データはappendできません。

実際のエラーはこんな形です。
```
DML statements are only supported over tables that have data stored in BigQuery. Unsupported table:~~~
```

external_data_configurationを使ったコードはこちらです。
```yaml
resource "google_bigquery_table" "default" {
  dataset_id = google_bigquery_dataset.default.dataset_id
  table_id   = "bar"

  time_partitioning {
    type = "DAY"
  }

  labels = {
    env = "default"
  }

  schema = <<EOF
[
  {
    "name": "permalink",
    "type": "STRING",
    "mode": "NULLABLE",
    "description": "The Permalink"
  },
  {
    "name": "state",
    "type": "STRING",
    "mode": "NULLABLE",
    "description": "State where the head office is located"
  }
]
EOF

}

resource "google_bigquery_table" "sheet" {
  dataset_id = google_bigquery_dataset.default.dataset_id
  table_id   = "sheet"

  external_data_configuration {
    autodetect    = true
    source_format = "GOOGLE_SHEETS"

    google_sheets_options {
      skip_leading_rows = 1
    }

    source_uris = [
      "https://docs.google.com/spreadsheets/d/123456789012345",
    ]
  }
}
```


## まとめ
Terraformのドキュメントをパッと見たときにはBigQueryは外部テーブルとして作成する使い方しか記載がなく、データを溜める時にappdendできずに非常に困っていました。

手順としては
1. ネイティブテーブルを作成する。
1. 作成したネイティブテーブルにデータを流し込む

で問題なくいけました。

データ基盤を構築する上でデータが日々追加されるテーブルは多いのでこの
Azure-Arc Enabled Serverを別のサブスクリプション/リソースグループに移行する方法

### はじめに

後からリソースグループを変更したい時ってありますよね。今回はAzure PowerShell ModuleでAzure-Arc Enabled Serverのリソースプールを移行する方法を紹介します。

私の記事ではお馴染み[Thomas Maurer氏の記事](https://www.thomasmaurer.ch/2023/04/how-to-become-a-microsoft-mvp/)を参考にさせていただいています。

### 手順

使うコマンドは以下です。
```
# Get Azure Arc-enabled Server you want to move
$Resource = Get-AzResource -ResourceType "microsoft.hybridcompute/machines" -ResourceName <ResourceName>
# Move Azure Arc-enabled server to new resource group and subscription 
Move-AzResource -ResourceId $Resource.ResourceId -DestinationResourceGroupName <DestinationResouceGroupName>
```

できました。やったね。処理完了まで5分程度かかったのですがプログレスバーが0%から動かなくて怖いですが完了すると一気に動きます。
![MoveRG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/70202343-d04c-198d-a699-71b19cd11eeb.png)

ちなみにもちろんPortalからも簡単に移動できます。
![MoveRG_Portal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/2fb04fa1-05b5-3cb6-5406-6c7b9adbedfe.png)
BeautifulSoupでcssセレクタを使い細かく要素を指定する

findよりselectのほうがいろいろ使いやすいので
忘れないようにメモ

## 練習コード

### HTML
```html
<div id="a">
    <div id="b">
        <p class="hello">こんにちは</p>
    </div>
    <p class="morning">おはよう</p>
    <p class="night">おやすみ</p>
</div>
```

### python
```python
from bs4 import BeautifulSoup

soup = BeautifulSoup(html, "lxml")
#前方一致
print(soup.select('p[class^="he"]'))
#後方一致
print(soup.select('p[class$="ing"]'))
#部分一致
print(soup.select('p[class*="ig"]'))
#直下の子要素のみ
print(soup.select('#a>p'))
#配下の要素
print(soup.select('#a p'))
#以降の要素
print(soup.select('#b~p'))
#隣接の要素
print(soup.select('#b+p'))
```

### 出力
```
[<p class="hello">こんにちは</p>]
[<p class="morning">おはよう</p>]
[<p class="night">おやすみ</p>]
[<p class="morning">おはよう</p>, <p class="night">おやすみ</p>]
[<p class="hello">こんにちは</p>, <p class="morning">おはよう</p>, <p class="night">おやすみ</p>]
[<p class="morning">おはよう</p>, <p class="night">おやすみ</p>]
[<p class="morning">おはよう</p>]
```
ChatGPTを使ってラブレターを代筆してくれるWebアプリケーションを作ってみた

# はじめに

色々な使用例が既にあるのですが、何か作ってみたいなと思ったら簡単にできたので記事にしてみます。

# 開発環境

- ChatGPTアカウント
- Python3.x系
- Flask

# OpenAI APIキーの取得

詳しく説明されているのでこちらをご参照下さい。

https://auto-worker.com/blog/?p=6988

# ライブラリのインストール

```sh:
pip3 install openai
```

# ファイル構成

- main.py
- templates/letter.html

# スクリプト

```py:
#!/usr/bin/env python3

from flask import Flask, request, render_template
import openai

app = Flask(__name__)

openai.organization = "org-[自分のOrganization ID]"
openai.api_key = "sk-[取得したAPIキー]"

@app.route('/', methods=["GET", "POST"])
def index():
    
    msg = ""
    
    if len(request.form) > 0:
        vals = request.form
        txt = """
私の名前は「{}」
相手の名前は「{}」
二人の関係性は「{}」
馴れ初めは「{}」
相手の好きなところは「{}」
手紙を受け取った後に望むことは「{}」
""".format(
    vals["sender"],
    vals["reciever"],
    vals["relation"],
    vals["at_begining"],
    vals["point"],
    vals["what_you_want"]
)
        try:
            rs = openai.ChatCompletion.create(
                model="gpt-3.5-turbo",
                messages=[
                    {"role": "system", "content": "あなたは手紙の代筆をしている人です"},
                    {"role": "user", "content": "大好きな人に思いを伝えるための手紙を送りたいので文章を考えてもらいたい"},
                    {"role": "assistant", "content": "詳細を教えて頂けますか？"},
                    {"role": "user", "content": txt},
                ]
            )
        
            msg += rs['choices'][0]['message']['content']
            
        except:
            
            msg += """
しばらく待ってから再度実行してみて下さい。
"""

    return render_template("letter.html",
        msg=msg
    )

if __name__ == '__main__':

    app.run(host='0.0.0.0', port=8080, debug=False)
```

# テンプレートファイル

```html:
<html lang="ja">
	<head>
		<meta charset="utf-8">
        <meta name="viewport" content="width=device-width" >
		<title>ラブレター代筆</title>
	</head>
	<body>
		
		<div id="page">
			
			<div id="header">
				<h1>ラブレター代筆</h1>
			</div>
			
			<form id="body" method="post">
				<table>
					<tr>
						<td>相手の名前 ：</td>
						<td><input type="test" name="reciever" value="" /></td>
					</tr>
					<tr>
						<td>あなたの名前 ：</td>
						<td><input type="test" name="sender" value="" /></td>
					</tr>
					<tr>
						<td>関係性 ：</td>
						<td><input type="test" name="relation" value="" /></td>
					</tr>
					<tr>
						<td>馴れ初め ：</td>
						<td><input type="test" name="at_begining" value="" /></td>
					</tr>
					<tr>
						<td>好きなところ ：</td>
						<td><input type="test" name="point" value="" /></td>
					</tr>
					<tr>
						<td>求めること ：</td>
						<td><input type="test" name="what_you_want" value="" /></td>
					</tr>
					<tr>
						<td>&nbsp;</td>
						<td><input type="submit" name="submit" value="送信" /></td>
					</tr>
				</table>
			</form>
			
			<div id="answer">
				<pre>{{msg}}</pre>
			</div>
		</div>
	</body>
</html>
```

# 実行

```sh:
python3 main.py
```

実行したらWebブラウザでアクセスしてみます。

http://localhost:8080

できた！

参考までに完成したWebアプリケーションをこちらでお試し頂けます。

http://160.16.98.190:8080/letter
納入商品の作成


質問の回答としてフローで作成してみました。
+ [納入商品に取引先と取引先責任者を自動紐付けしたい](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Pk0aa)


# フロー全体
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/f5a2eefa-973f-dd7a-9169-a3f6eb758267.png)

このApex トリガーを参考にどのフィールドに何をセットしたらいいかを確認しました。
商談商品から納入商品を作ればいいことが分かります。

https://developer.salesforce.com/forums/?id=9060G000000IBEXQA4


取り合えずは上記と同じで商談が成約としてクローズされたら納入商品をつくることとします。

# レコードトリガーフローの開始

今回は商談で起動しますが、別のオブジェクトを作成するのでApexトリガのafterトリガと同じということで、フローの最適化ではアクションと関連レコードを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/7bcb7c83-17fe-7e2f-ea77-a972aaff190c.png)

# 変数の確認

+ AssetRecord

納入商品に値をセットするための変数です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/96ace5cc-adf1-b7f4-4616-3553365c7474.png)

+ AssetCollection

上記変数を格納して一括作成に使います

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/6bd933e7-0298-2212-9c12-5c652dc7d75d.png)

# 取引先責任者の取得

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/5dc758b7-55fc-e3e2-e106-9444379fba9f.png)


# 商談商品の取得

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9d20cddc-57a5-53bf-65d8-6981635221e1.png)


# 商談商品でループ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/a299577d-f5eb-2362-5447-1ff273ca1856.png)


# 納入商品に値をセット

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/6a026e2d-9727-ed1a-eed0-9fcae1521dcd.png)

{!AssetRecord.AccountId}  <-- {!$Record.Account.Id}
{!AssetRecord.Name}       <--- {!Loop_OpportunityLineItem.Name}
{!AssetRecord.Product2Id} <-- {!Loop_OpportunityLineItem.Product2.Id}
{!AssetRecord.Quantity}   <--- {!Loop_OpportunityLineItem.Quantity}
{!AssetRecord.Price}      <--- {!Loop_OpportunityLineItem.UnitPrice}
{!AssetRecord.InstallDate} <--- {!$Record.CloseDate}
{!AssetRecord.ProductCode} <--- {!Loop_OpportunityLineItem.ProductCode}
{!AssetRecord.ContactId}  <---  {!getContact.Id}


# 納入商品のコレクション変数に追加

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/5b211814-07cd-94dc-b3b8-c16a97050e3c.png)


# 納入商品の一括作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/77433ffe-957e-889e-eb2f-0abbf5f7ad16.png)
CCNA 備忘録（Cisco IOS 超基本コマンド編）

# 基本操作

`enable` 特権モード
`configure terminal` グローバルコンフィグレーションモード
`interface fa 0/0` インターフェースモード **Fa Gi**
`line vty 0 4` ラインモード **接続方法　console vty AUX**
`exit` 一個戻る　**特権で使うとログアウトするから注意**
`end` 各コンフィグレーションから特権に戻る
`disable` 特権からユーザーに戻る


# IPv4の設定
`(config)#interface fastEthernet 0/0` インターフェースの指定
`(config-if)#ip 192.168.1.0 255.255.255.0` IPアドレス サブネットマスク
`(config-if)#no shutdown` インターフェースの有効化

# IPv6の設定
`(config)#ipv6 unicast-routing` IPv6ルーティングの有効化
`(config-if)#ipv6 address fe80:::1 link-local`
 **リンクローカル**ユニキャストアドレスの設定　**fe80:で始まるアドレス**
`(config-if)#ipv6 address 2001:db8:aaaa::1/64`
**グローバル**ユニキャストアドレスの設定　**２か３で始まるアドレス**
CCNA 備忘録 チートシート（優先順位編）

# 値の大きいほうが優先度高くなるやつ
* **OSPFのプライオリティ値** 
def.1 range.0~255 
* **OSPFのルータID**　**(10進数12桁)**　255.255.255.255　≒IPv4アドレス
[router-id > loopback IP > 物理IF IP]　
* **HSRPプライオリティ値**
def.100　[priority > 物理IF IP]
* **GLBPプライオリティ値**
def.100 Max.255 
* **VRRPプライオリティ値** 
def.100 Max.255
*(注)物理IPアドレスを仮想IPアドレスに設定した場合はそのルータがMasterになる*
* **QoS CoS値**
def.0 range.0~7


# 値の小さいほうが優先度高くなるやつ
* **アドミニストレーティブディスタンス AD値**
下に別表
* **OSPFメトリック コスト**
100Mbpsを帯域幅で割る Max.1
* **EIGRPメトリック**
def.帯域幅と遅延を足す
* **RIPメトリック** 
ホップ数（ルータを跨ぐ回数）
* **STP BPDUのブリッジID**　**(16進数16桁)** FFFF:FFFF:FFFF:FFFF:: ≒IPv6アドレス
ブリッジプライオリティ(頭4桁)+MACアドレス
ブリッジプライオリティは4096単位で指定　def.32768　
* **STP ルートポート選出**　パスコストは帯域参照
[ルートブリッジへのパスコスト累計 > ブリッジID > ポートID]
帯域別パスコスト値 10Gbps = **2**　1Gbps = **4**　100Mbps = **19**
* **Syslog レベル**　range.0~7
0:緊急 1:警報 2:重大 3:エラー 4:警告 5:通知 6:情報 7:デバック

## AD値　早見表
| ルート                | AD値 | 
| :-------------------: | :---: | 
| 直接接続：C           | 0    | 
| スタティックルート：S | 1    | 
| eBGP：e               | 20   | 
| EIGRP：D              | 90   | 
| OSPF：O               | 110  | 
| IS-IS：i 小 L1 L2     | 115  | 
| RIP：R                | 120  | 
| iBGP：Ⅰ大            | 200  |
npmとnpx

## npm
言わずと知れたNode JSのパッケージマネージャ。
`npm install`してパッケージをインストールし利用する。

## npx
Node Package Executerの略
`npm install`していない状態でもパッケージをインストールし実行して最後に消してくれる。
平たく言うと、インストールしていないパッケージを実行できます。
例えば、angular/cliやcreate-react-appなどのCLIを`npm install -g`する必要ない = グローバルを汚染せずに実行できます。

### npmでやると
```shell
npm install -g @angular/cli # グローバルインストールしないといけない
ng new project-name
```
```shell
npm install -g create-react-app # グローバルインストールしないといけない
create-react-app project-name
```
私は普段nでNodeのバージョンを切り替えてますが、グローバルインストールしたパッケージのバージョンまで切り替えできないので困ってました（複数プロジェクトに関わっていて、それぞれで利用しているangular/cliのバージョンが違った）
この問題が`npx`を使うと解決できます。


### npxでやると
```shell
# 一時的にインストールされ、ng new実行後に消される
npx -p @angular/cli ng new project-name
cd project-name
ng # command not found. 削除されてるので
npm run ng # OK. package.jsonにローカルのngコマンドが登録されてる
```
```shell
# 同じく一時的にインストールされ、Reactアプリケーション作成後に削除される
npx create-react-app project-name
```

今までリファレンス等見て何も考えずにnpxを実行してましたが、こういう意味だったんですね。
超便利。
いきなりwindows PC で作業しろと言われてキーボード配列がUSに変更できずにいつもイライラしてしまう君へ

## 概要

いつもはLinuxとかMacPCで英語配列のキーボードで作業しているが、
業務でウィンドウズPCを使うことになり、
キーボードが日本語配列の設定なので変更したい。

結果ググってみたもののいろいろなドキュメントに振り回されて
変更できずにイライラしてしまったあなた。

一度設定したつもりだったが、数ヶ月後にまたWindowsで作業することになり、
その度に設定の仕方を忘れて検索に時間を使ってしまうあなた。

そのイライラは**２秒で解決**して快適に英語配列で作業を開始しましょう。


## 配列の変更方法

1. 備え付けの日本語キーボードを繋いだままにします。
2. 英語配列のキーボードを新しくつなぎます。
3. 備え付けの日本語キーボードで、**Windowsボタンを押しながら、スペースキーを押します。**
4. 英語配列キーボードに変更完了します。


Windows10 で動作確認済みです。
11は試していません。
【ServiceNow】物理削除履歴の残し方と削除データの復元方法

本記事では、以下の３つについてご紹介します。
・物理削除の履歴を残すための設定
・削除履歴の確認方法
・削除データの復元方法

物理削除の履歴を残すための設定
---
**Audit の有効化**
　１．フィルターナビゲーターで All > System Definition > Dictionary と検索します。
　２．以下の条件のレコードを開きます。
　　　Table＝履歴を残したいテーブル（例として、sys_user_group を設定します。）
　　　Column name＝空白
　　　Type＝Collection
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/87d7f40f-35e0-cd28-0ea0-f6bdec4ac9da.png)
　３．Audit チェックボックスをオンにし、レコードを更新します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/007c3127-62e4-f49b-a5e4-6ea0afffd4db.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/cc3b8643-1402-6274-5b3f-8d2696590f98.png)

以上で、物理削除の履歴を残すための設定は完了です。

削除履歴の確認方法
---
該当のテーブルでレコードの削除をしたとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/2600fbd7-f2ae-5c88-9706-8603e2a9df56.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/a10a044b-951e-0104-f3a6-9a984ce7062b.png)

　１．sys_audit_delete テーブルを確認すると、レコードが追加されています。
　　　※フィルターナビゲーターで「sys_audit_delete.list」と検索します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/d966c252-68dc-5db8-9ec6-6066a6f231df.png)
　２．レコードを開くと、削除した内容を確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/967a1c28-2014-d504-7705-31b1751953c1.png)

削除データの復元方法
---
一度物理削除したデータを復元するには、以下の操作を行います。

:::note warn
ただし、以下に注意してください。
※１ 単一テーブルのレコードの delete をもとに戻すだけのため、カスケードされているテーブルのレコードや他テーブルとのリレーションは元には戻りません。
※２ sys_audit_delete テーブルで検索に使える要素が少ないため、対象レコードが特定できない可能性もあります。少しでも不安を感じたら、元に戻さず、手動でデータを作成しなおすことを推奨します。
:::

今回は、前章の「削除履歴の確認方法」で削除したデータを復元させます。

１．sys_audit_delete テーブルを開きます。

２．削除してしまったレコードを検索して特定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/9e08ea0a-a715-f7da-15d6-519cda38337b.png)
３．レコードを開き、「レコードの削除の取り消し」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/82e2cebf-e5a4-f709-1988-2c3ac6f424c3.png)
４．sys_audit_delete テーブルからレコードが無くなり、データが復元されています。
＜sys_audit_delete テーブル＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/f5313a66-9f75-10aa-f016-fcc4459a71c1.png)
＜データが元々登録されていたテーブル＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/d2e9edc0-5a5e-4db7-ed42-f9a13de91d75.png)

以上で、削除データの復元は完了です。

おわりに
---
今回は物理削除の履歴の残し方、削除データの復元方法について紹介させていただきました。

レコードの更新履歴だけでなく、削除履歴も見たい！という場合は是非試してください。
また、システムの開発において、基本的には論理削除で対応することが多いかと思いますが、誤ってデータを削除してしまう可能性が無いとは言い切れないので、是非ご活用ください。
キャンペーン評価の手法 - 評価測定ケースの考察 - 2 

:::note
この本書は2017年4月1日にTeradata Japanのブログに掲載された内容を、再掲載したものです。
掲載内容の正確性・完全性・信頼性・最新性を保証するものではございません。
また、修正が必要な箇所や、ご要望についてはコメントをよろしくお願いします。
:::


著者 山本 泰史 （やまもと やすし）

# 評価測定ケースの考察 - 2

今回ご紹介するのは互いに影響を与え合うキャンペーンのケースです。お互いに相乗効果を与えるケース、そしてお互いに悪影響を与え、食い合ってしまうケースの 2つを例示します。

<img width="700" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2768546/fcc00d56-64ca-1ff6-c51c-b98fb1a49224.png">

この例では、2つのキャンペーンを連続して、マルチステップ型のキャンペーンとして実施した場合と、それぞれ個別で実施した場合の比較を実施します。 キャンペーン#4 はTVCMで “大衆” に対して影響を与えるキャンペーンです。これに対して、Web上で会員向けに閉じた世界で実行するのがキャンペーン#5 です。キャンペーン#4 とキャンペーン#5 を、それぞれ独立して(影響を与えない程度に間隔を空けて)実施した場合、それぞれ利益率が122％と200％となります。採用/棄却の判断基準が150％であるとすると、キャンペーン#4 は通常であれば棄却されなければなりません。


しかしながら、キャンペーン#4 と#5 を連続して実施した場合、この例ではTVCMであるキャンペーン#4 が実施されると、キャンペーン#5 にも良い影響を与えることが想定されます。 実際に連続して実施した場合をキャンペーン#5' として測定すると、300％と100％分の上乗せを実現したことが分かります。 キャンペーン#4 そのものは収益性がないのですが、#4+#5' で合わせた利益率では245％となり、キャンペーン#5' における増分効果をキャンペーン#4 に起因するものであるとして、この結果を足しこんで計算しなおすと( キャンペーン#4' ) 344％の利益率に改善されることが分かります。


この結果、キャンペーン#4 は単体では利益率の基準を満たしませんが、キャンペーン#5 と一緒に実施することによって(依存することによって)、必要な利益率を達成できるキャンペーンとなることが分かります。この例はそれぞれのキャンペーンの依存関係を明らかにするための例であり、常にTVCMの効果がない、もしくはTVCMは他のキャンペーンへの依存がなければ効果がないということを意味しているわけではありません。 また逆に他のキャンペーンに依存してもやはり効果はない(増分効果が少ない)ということも考えられます。幾つかのキャンペーンをここでは一つの大きな親キャンペーンと捉え、その中で子キャンペーンをどのような順番で並べるか、またはどのキャンペーンを取捨選択するかを判断していく中でキャンペーンの効果が最大になる組合せを見つけることに主眼が置かれています。これはマルチステップ型のキャンペーンを実行していく中では重要な検討方法のひとつとなります。

<img width="700" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2768546/f8f87c01-2a99-f5b7-53c9-4d5ba97dd7e8.png">


もう一つ複数のキャンペーン間の影響を理解するためのケースをご紹介します。 キャンペーン#6 はある商品A の割引キャンペーンであるとします。これに対して商品A の後継として新たに販売開始された商品A' のキャンペーンをキャンペーン#7 として考えます。 採用基準である利益率は150％です。これに対して、2つのキャンペーンを連続して実行した場合、キャンペーン#7 は88％と棄却されるべき利益率しかもたらさないことになります。キャンペーン#6 と#7 を合わせても142％の利益率しか有りません。例えばこの商品がリピート性の高い商品(例えば化粧品のような商品)で、消費し尽くすまでにある程度の期間がかかる場合、新商品に乗り換えたくとも今あるものを使い切らなければならないとすれば、新商品への手は伸びないことになります。それどころか旧商品の在庫一掃と思われて悪い印象を与えることも考えられます。逆に新商品の先行情報が流れており、そのメッセージが魅力的であれば(例えば美肌効果が今までの1万倍!!!等)、買い控えが発生してキャンペーン#6 は想定した結果をもたらさないかもしれません。いずれにしてもこの例では2つのキャンペーンのどちらかが片方の足を引っ張ることになります。


反対に、この2つのキャンペーンの間隔を十分に空け、それぞれを独立したキャンペーンとして実施した場合を考えて見ましょう。 例えば標準的な商品の耐用期間から逆算したタイミングにキャンペーン#6 を実施して、耐用期間を過ぎるちょっと前のタイミングでキャンペーン#7 を実施すれば、それぞれの影響を排除することが可能になります。もしかしたら使い切るタイミングが揃うためにキャンペーン効果はもっと良くなるかもしれません(ちょっと姑息かもしれませんが、これもマルチステップ型キャンペーンの一例といえるでしょう)。


このケースではタイミングを修正したキャンペーン#7' において181％の利益率を導き出し、キャンペーン#6+#7' では190％の利益率となり、単体、連結共に基準を上回ることになります。前述したケースとは逆に、マルチステップ型のキャンペーンとして捉えるのではなく、それぞれを個別のキャンペーンとして独立させることによって利益率が高くなる可能性、もしくは十分な間隔を空けたマルチステップ型キャンペーンとして認識することも考慮に入れなければなりません。


#### Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)
【ServiceNow】NextExperience での検索の使い方

本記事では、Tokyo バージョンより新たに機能が追加した検索方法についてご紹介します。

ワークスペースの指定と検索が同時にできる機能なので、ワークスペースを多く使用している場合はとても利便性が上がると思います。

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

検索の追加機能について、公式ドキュメントでは以下のように記載されています。
※公式ドキュメントのリンク：https://bit.ly/3Kj2V4c

＜英語＞
>Global search enables you to search multiple record types at once from the Next Experience Unified Navigation search field. Search returns the results that are most relevant to you, grouped by source, or takes you directly to a record that exactly matches your search query. You can switch between global search results and results from workspace applications that you have access to.

＜和訳＞
>グローバル検索では、Next Experience Unified Navigation 検索フィールドから複数のレコードタイプを一度に検索できます。検索では、最も関連性の高い結果がソース別にグループ化されて返されるか、検索クエリに完全に一致するレコードに直接移動します。グローバル検索結果と、アクセス可能なワークスペースアプリケーションの結果を切り替えることができます。


とのことで、グローバル検索結果とワークスペースでの検索結果を切り替えることが可能になったそうです。

具体的にどのような検索ができるのか、PDI 環境を使って調べました。

NextExperience での検索の使い方
-------
Unified Navigation 検索フィールド（画面上部の検索窓）にて、以前は Global 検索の
みが可能でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/3eb15d58-11cc-d11a-9db9-2a472dc197e6.png)

NextExperience ではワークスペースを指定した検索も可能となりました。
インシデントレコードを検索して、動きを確認していきます。

＜Global 検索＞※初期設定は Global 設定になっています。
レコード番号を検索し、結果をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/cbd81e2e-ec47-bbd8-e70d-a64bee7fb96d.png)

インシデントレコードを開くことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/e947210d-f8da-1f0b-a3ae-c23f9b20eb1a.png)

＜ワークスペースを指定した検索＞
開きたいワークスペースを選択して、レコード番号を検索します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/05e8098a-dbf7-833c-be6e-c465682bb5d9.png)

検索結果を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/84c5fb21-7024-7af0-636c-63013a0a9d37.png)

ワークスペースでレコードを開くことができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/f507e667-da48-3bc1-c359-8a0c4ec49506.png)

おわりに
---
本記事では、NextExperience での検索方法について紹介しました。
ワークスペースを多く使用している場合はとても役立つ便利機能だと思います。
是非ご活用ください。
Shopifyでブログページに他のファイルをinclude表示する方法。

Shopifyでブログページに他のファイルをinclude表示する方法。

1.Snippetsフォルダにliquidファイルを作成する。(例:footer-blog.liquid)
2.Section/main-article.liquidに{% include 'footer-blog' %}を追加する。

追加する場所は下記。51行目ぐらい
        {%- when 'content'-%}
          <div class="article-template__content page-width page-width--narrow rte" itemprop="articleBody" {{ block.shopify_attributes }}>
              {{ article.content }}
      {% include 'footer-blog' %}
          </div>
負荷試験ツール一覧メモ

## 負荷試験ツール一覧

1. **JMeter**
   - [公式ウェブサイト](https://jmeter.apache.org/)
   - [ユーザーガイド](https://jmeter.apache.org/usermanual/index.html)

2. **Gatling**
   - [公式ウェブサイト](https://gatling.io/)
   - [ドキュメント](https://gatling.io/docs/current/)

3. **Locust**
   - [公式ウェブサイト](https://locust.io/)
   - [ドキュメント](https://docs.locust.io/en/stable/)

4. **k6**
   - [公式ウェブサイト](https://k6.io/)
   - [ドキュメント](https://k6.io/docs/)

5. **LoadRunner**
   - [公式ウェブサイト](https://www.microfocus.com/en-us/products/loadrunner-load-testing/overview)
   - [ドキュメント](https://admhelp.microfocus.com/lr/en/latest/help/WebHelp/Content/Resources/_TopNav/_TopNav_Home.htm)

6. **Taurus**
   - [公式ウェブサイト](https://gettaurus.org/)
   - [ドキュメント](https://gettaurus.org/docs/)

## 検討するための観点案
- プロトコルのサポート
- スクリプト作成の容易さ
- 拡張性
- コミュニティとサポート
- レポートと分析
- 価格
- 環境の互換性
- 実行環境の柔軟性

## 所感（ぱっと見）
- LoadRunnerは良さげでしたが、OSSではなさそうね
- OSSをベースにシナリオ作成して見て比較するに当たりどのような観点が良いかな？
ELBの概要

# ロードバランサについて
直接Webサーバーにアクセスするのは単一障害点になる。
⇒Webサーバーを複製して冗長構成にする。
↓
問題点
・アクセスポイントが分かれてしまう。
・サーバーが正常かチェックしなければならない。
※異常な状態のサーバーへは通信を自動的にストップさせたい。
・セキュリティの問題：直接Webサーバにアクセスさせるのはよろしくない。（webサーバーに通信の複合を処理させる必要がでてくる。）
↓
**ELB** を使用して課題解決する。

# ELB(Elastic Load Balancing)
・ロードバランサにはDNS名のアクセスポイントが付与される。
→アクセスポイントを一つにし、負荷を分散させる。
・ヘルスチェック機能がある。
→異常なインスタンスを認識し、通信をストップする。
・ELBに証明書を付与することでSSL通信の終端となる。
→HTTPS通信を復号する処理を担う。（SSL Termination）

# ELBの種類
・ALB（アプリケーション層（L7レイヤー））で、HTTPやHTTPSのリクエストの負荷分散に使用。
・NLB（ネットワーク層（L4レイヤー））で、TCPやUDPのトラフィック分散に使用。
・CLBは以前使われていた古いタイプのロードバランサ。
・ELBのみパブリックサブネットに配置して、EC2やRDSはプライベートサブネットに配置してセキュリティレベルを高めることが可能。
・内部向けロードバランサにはNLBが使用されることが多い。（内部はALB、外部はNLBを使用）
指定した文字列が含まれる親要素取得

<div class="tree_root">

    <ul>
        <li>
            <div class="tree_item_1">
                <span class="tree_name">
                    <a herf="/hoge/test1">test1</a>            
                </span>
            </div>
            <div class="tree_item_2">
                <input class="bikou" type="text">
            </div>
        </li>
        <li>
            <div class="tree_item_1">
                <span class="tree_name">
                    <a herf="/hoge/test2">test2</a>            
                </span>
            </div>
            <div class="tree_item_2">
                <input class="bikou" type="text">
            </div>
        </li>
    </ul>
</div>



※編集とプレビューで表示が違う。どうすれば正しく書けるかわからない
※編集のほうが正しいので、これを使用するさいは編集モードでみる
SelenideElement ele = $(".tree_root").$$("tree_name")
                                     .filterBy(Condition.exactTect("test1"))
                                     .first()
                                     .closet("li");

//表示されているか（visible?のほうがいいかも）
ele.should(Condition.exist));

ele.$(".bikou").val("test1の備考を記入");
リストを変更しようとするとunsupportedOperationExceptionが起こる


リストを変更しようとするとunsupportedOperationExceptionが起こる
例）testList.remove(0)

List<String> testList = List.of("test1","test2");
List.ofは中身が変更できない

リストの中身を変更する可能性がある場合は以下のようにする
List<String> testList = new ArrayList<String>(Arrays.asList("test1","test2"))
React-Youtubeで使うビデオIDを正規表現で取り出す

# 結論

urlにはYoutbe動画のurl叩き込んでください。

```ts
  const getVideoId = (url: string): string | undefined => {
    const match = url.match(
      /^(?:https?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))([\w-]{11})(?:\S+)?$/
    );
    return match?[1] : undefined;
  };
```
Pythonでメールを送りたい

メール送信を自動化したかったので、Pythonで作ってみました。

# テキストメールを送信する

下のプログラムは、SMTPS（TCP465）のプロトコルを使ってプレーンテキストを送信します。

```python:
import smtplib
from email.mime.text import MIMEText

msg = MIMEText("メールの本文を書きます","plain","utf-8")
msg["From"] = "xxx@xxx.xxx"
msg["To"] = "yyy@yyy.yyy"
msg["Subject"] = "タイトルを書きます"

smtp = smtplib.SMTP_SSL(host="プロバイダのSMTPメールサーバ",port=465)
smtp.login("ユーザ名","パスワード")
smtp.send_message(msg)
smtp.quit()
```

# 添付ファイルを送信する

下のプログラムは、SMTPS（TCP465）のプロトコルを使ってプレーンテキストと添付ファイルを送信します。

```python:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication

msg = MIMEMultipart()
msg.attach(MIMEText("メールの本文を書きます","plain","utf-8"))
msg["From"] = "xxx@xxx.xxx"
msg["To"] = "yyy@yyy.yyy"
msg["Subject"] = "タイトルを書きます"

with open("file.txt","rb") as f:
    mime_file = MIMEApplication(f.read())
mime_file.add_header("Content-Disposition", "attachment", filename="file.txt")
msg.attach(mime_file)

smtp = smtplib.SMTP_SSL(host="プロバイダのSMTPメールサーバ",port=465)
smtp.login("ユーザ名","パスワード")
smtp.send_message(msg)
smtp.quit()
```

# おわりに

今回はSMTPSを使いましたが、使用するプロトコルが違うと別のメソッドを使うみたいです。
MinecraftのサーバにRCONで接続する

# RCONとは

- RCONはRemote Consoleの略称
- ゲームサーバをリモートで管理するための機能全般を指す用語
- Minecraft以外でも、ARK: Survival EvolvedやBattlefield、Call of Duty、Rust等、ユーザ自身がサーバをホスティングできるFPSやマルチプレイのゲームを中心に広くサポートされている

## プロトコル

- RCONのプロトコルの仕様はRFC等の形で標準化されているわけではなく、一般的に各ゲームによって独自の仕様を持つ
- Minecraftの場合は、SteamやVALVE INDEXを開発・運営している[Valve Corporation](https://www.valvesoftware.com/)がゲームエンジンの[Source Engine](https://developer.valvesoftware.com/wiki/Source_Engine_Features)で採用していた[Source RCON Protocol](https://developer.valvesoftware.com/wiki/Source_RCON_Protocol)の仕様(パケットのフォーマット等)をベースに、[Minecraft固有のコマンド](https://minecraft.fandom.com/wiki/Server.properties)を使用できるよう拡張している
- MinecraftのRCONに関する公式なプロトコルの仕様書やクライアントの実装は存在しない
- MinecraftのRCONのプロトコルは、トランスポート層にTCPを使用するアプリケーション層のプロトコルで、テキストベースで通信を行い、デフォルトでは通信は暗号化されない(パスワードもプレーンテキストで送信される)といった特徴を持つ
- そのため、安全に使用したい場合は、SSHトンネリングやVPNを用いて通信経路を別途、暗号化する必要がある

## クライアント

- MinecraftのRCONのクライアントはいくつか選択肢があるが、代表的なクライアントには[mcrcon](https://github.com/Tiiffi/mcrcon)が挙げられる
- mcrconはCで実装されたCLIのクライアントでクロスプラットフォーム対応(Linux、macOS、Windows)している

# 検証

- 実際に、MinecraftのサーバにRCONで接続してみる
- OSはmacOS Venturaにて検証を行った
- MinecraftのサーバはMinecraft: Java Edition 1.19.4を使用している
- RCONのクライアントにはmcrconを使用する

## サーバの設定

- 事前にMinecraftのサーバでRCONを有効化し、任意のポートを設定(デフォルトは`25575`)し、RCONのパスワードを設定しておく
- Minecraftのサーバでファイアウォールやパケットフィルタリングが設定されている場合は、TCPのポート25575番のインバウンドの通信を許可しておく

```properties:server.properties
...
rcon.port=25575
...
enable-rcon=true
...
rcon.password=password
...
```

## mcrconのインストール

- macOSの場合はソースコードからビルドする
- LinuxやWindowsの場合はバイナリも提供されている
    - Releases: https://github.com/Tiiffi/mcrcon/releases

```bash
$ git clone https://github.com/Tiiffi/mcrcon.git
$ cd mcrcon/
$ make
$ sudo make install

# mcrconのバージョンが表示されたらインストール成功
$ mcrcon -v
mcrcon 0.7.2 (built: Apr 19 2023 18:21:37) - https://github.com/Tiiffi/mcrcon
Bug reports:
	tiiffi+mcrcon at gmail
	https://github.com/Tiiffi/mcrcon/issues/
```

## mcrconから接続

```bash
# -HオプションにはMinecraftのサーバのIPアドレスを指定する
# -tオプションはインタラクティブモードで起動する
$ mcrcon -H X.X.X.X -P 25575 -p password -t
Logged in.
Type 'Q' or press Ctrl-D / Ctrl-C to disconnect.
>

# 試しにホワイトリストの確認をしてみる
>whitelist list
There is/are 1 whitelisted player(s): XXXXXXXX

# Ctrl + d で抜ける
>^D
```

## SSHトンネリングする

- MinecraftのRCONは、デフォルトでは通信経路が暗号化されないため、盗聴や改ざんのリスクが存在する
- SSHトンネリング(SSHローカルポートフォワーディング)の仕組みを利用することで通信を暗号化し、安全な通信を実現できる

```bash
# -fオプションはバックグラウンド実行するためのオプション
# -Nオプションはシェルを起動しないようにするためのオプション
# -LオプションはSSHローカルポートフォワーディングを設定するためのオプション
# この場合、localhost:25575への通信がSSHで暗号化され、X.X.X.X:25575に転送される
$ ssh -f -N -L 25575:localhost:25575 username@X.X.X.X

# -Hオプションにはlocalhostを指定する
$ mcrcon -H localhost -P 25575 -p password -t
Logged in.
Type 'Q' or press Ctrl-D / Ctrl-C to disconnect.
>
```

## SSHトンネリングの終了

```bash
# ポート25575番でリッスンしているプロセスを調べる
$ lsof -i :25575 | awk '{print $1, $2, $5, $9, $10}'
COMMAND PID TYPE NAME
ssh 58995 IPv6 localhost:25575 (LISTEN)
ssh 58995 IPv4 localhost:25575 (LISTEN)

# 該当するプロセスを終了する
$ kill 58995

# プロセスが表示されなくなった
$ lsof -i :25575

# RCONで接続できなくなった
$ mcrcon -H localhost -P 25575 -p password -t
Connection failed.
Error 61: Connection refused
```
vbsの作法 その64

# 概要
vbsの作法、調べてみた。
練習問題、やってみた。

# 練習問題
Windows11でInternet Explorer11を起動して、自動ログインせよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/4e749cf0-80e3-8e7a-05b1-bcd139d7c6dd.png)


# サンプルコード

```
Dim objIE
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Visible = True 
call objIE.Navigate("https://ev2-prod-node-red-ee25b632-b7c.herokuapp.com/list/login")
Do While objIE.Busy = True Or objIE.readyState <> 4
	WScript.Sleep 100
Loop
Dim doc
Set doc = objIE.Document
Dim id
Set id = doc.getElementsByName("user")
id.item(0).value = "admin"
Dim pass
Set pass = doc.getElementsByName("password")
pass.item(0).value = "password"
msgbox "ok"
doc.Forms(0).submit
Do While objIE.Busy = True Or objIE.readyState <> 4
	WScript.Sleep 100
Loop
Set objIE = Nothing




```

以上。
enebularでnode-red その13

# 概要
enebularでnode-redやってみる。
loginのテストするサーバーが欲しかったので、作ってみた。

# 参考にしたページ

https://qiita.com/sekiya-don/items/ca20cf05598475b4db86

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/40110bdd-7af2-3811-366e-849c1cafec0b.png)

以上。
【Ruby】Range#include?とRange#cover?について調べたら、CRubyのコードに辿り着いた

# Range#include? と Range#cover?の違いと内部のC言語に関して

## 前提

本記事の内容は'MRI'いわゆる'CRuby'を対象としています。
また、Rubyのバージョンは3.2です。

## 概要

Range#include? と Range#cover? は以下のように、どちらも引数が指定した範囲に含まれるかどうかを判定する時に使われています。

```ruby
(1.1..2.3).include?(1.1)    # => true
(1.1..2.3).cover?(1.1)      # => true
```

しかし、その違いがよく分からなかったため、本記事ではその違いについて説明します。
本記事では、公式ドキュメントへの理解を深め、最終的にはCRubyのコードについても考察していきたいと思います。

## 結論

公式ドキュメントでは書かれていなかったことで、自分で調べたことを補足していきます。

### Range#include?

公式ドキュメント

[Range\#include? \(Ruby 3\.2 リファレンスマニュアル\)](https://docs.ruby-lang.org/ja/latest/method/Range/i/include=3f.html)

> obj が範囲内に含まれている時に true を返します。そうでない場合は、false を返します。
> <=> メソッドによる演算により範囲内かどうかを判定するには Range#cover? を使用してください。
> 始端・終端・引数が数値であれば、 Range#cover? と同様の動きをします。

上記に対しての補足は、以下のとおりです。

2文字以上の文字範囲を比較する時、Range#include?はRange#eachを使用して、引数とRangeの各要素を`==`で比較することで、範囲内に要素が存在するかどうか判定します。
範囲の始点と終点が1文字の時で、引数が1文字なら始点および終点と引数を比較します。引数が1文字でないなら、問答無用でfalseになります。
また、始端・終端・引数が数値であれば、C言語では、`cover?`の処理の関数`r_cover_p`を呼び出しています。

[ruby/range\.c at v3\_2\_1 · ruby/ruby](https://github.com/ruby/ruby/blob/v3_2_1/range.c#LC1811)

### Range#cover?

公式ドキュメント

[Range\#cover? \(Ruby 3\.2 リファレンスマニュアル\)](https://docs.ruby-lang.org/ja/latest/method/Range/i/cover=3f.html)

> obj が範囲内に含まれている時に true を返します。
> Range#include? と異なり <=> メソッドによる演算により範囲内かどうかを判定します。 Range#include? は原則として離散値を扱い、 Range#cover? は連続値を扱います。（数値については、例外として Range#include? も連続的に扱います。）

上記に対しての補足は、以下のとおりです。

引数とRangeの始点および終点を`<=>`で比較して、範囲内にあるかを判定します。そのため、Range#include?よりも処理が早いです。


## 詳細

詳細は以下のZennのリンク先にあげています。

[【Ruby】Range\#include?とRange\#cover?の違い](https://zenn.dev/kochi_echo/articles/ruby_method_include_cover)

メソッドの違いが分からず、同じように困っている方に届きやすいように、Qiitaでも掲載しました。
中々、解決できなかった不具合が解決しました。

# 現象
Chrome拡張機能を作成しましたが、そのプラグインは、複数のタブを開いて連携動作するものです。
最初に履歴削除したり、不要タブを削除してきれいな状態で実行するとうまく動作します。
開くタブは一つの場合と二つ開く場合を想定しています。
ところが、何度もテストしていると二つのタブが複数ペアで開いてしまいます。それも回数が増えると開くタブも増えてしまいます。
すべてをリセットしてやり直すと、最初の一回は正常に動作します。タブのペアは一つしか開きません。続けて実行すると開くタブのペアは増えてゆきます。
# 試行錯誤した対策
どういうことなのだろうと考えましたが、検討が付きません。
どこかで、何らかの初期化がうまくいっていないのか。そこで、タブを開いているところに仕掛けをしました。
数カ所にconsole.log()を入れ、スクリプトの行番号も入れました。
どこの行のスクリプトで複数実行しているのかと。入れて、実行するとありました。続けて、実行している箇所がありました。タブを続けて開いています。なぜ、続けて開いているのだろうか考えました。
window.open()で、youtubeページと自前のブログページを開く処理をしているところです。このyoutubeページを一つでいいところをふたつ開いています。
# それまで、いろいろ考えたこと
この処理は、ページ内のテキスト文字を選択するとポップアップメニューを表示します。その選択したテキスト文字をクェリーにしてyoutubeで検索するものです。そこで、youtubeページを一つ開くものです。
もう一つは、youtubeで検索した動画を再生するためのプレーヤーページを開くものです。これらの二つのタブで連携動作するプラグインを開発していた時の現象です。
このポップアップメニューにある、実行ボタンをクリックすると二つのタブを開いて連携動作が始まります。
毎回、初回はうまく動作して、youtubeで検索した動画がプレーヤで実行できます。
ところが、続けて実行すると、その場合は、ページ内のテキスト文字を選択してポップアップメニューを表示することを行っても発生します。
原因は、このポップアップメニューにあるのではと検討をつけました。
# ポップアップメニーと実行ボタンの問題か
文字列の選択をするとポップアップメニューを表示するコードのところは特に問題はなさそうと考え、問題は実行ボタンをクリックするところかと疑いました。
この実行ボタンのところのコードは複雑になっています。数日前に、別のところの問題であるヒントを得ることができました。もしかしたら、ここでも、同じことが起こっているのではないかと期待はしました。
# 期待したことは
先日のヒントというのは、ポップアップ時のイベント処理登録です。
それは、ポップアップを行うたびにイベント登録が実行されています。これが不具合を起こしていました。ポップアップの度にイベント登録が積み重なり、それが続けて実行されていました。
そこで、ポップアップの先頭で一旦前回のイベント登録を削除し、その後にイベント登録を登録しました。これにより、イベント登録の積み重ねがなくなりました。
イベント登録を削除するjqueryのメソッドは.off()です。

```
//ここで、イベント処理を登録
//実行ボタンイベント登録
$("#exe_btn").on('click',()=>{
    .....
    .....
  
});
......
//前回登録した、イベント処理を削除する
......
$("#exe_btn").off('click');

```
たったこれだけの構文ですが、これで、タブの多重オープンがなくなりました。
# デモページ
[なつかしの曲(ポータル) https://tecoyan.blogspot.com](https://tecoyan.blogspot.com)
このリンク先のページで、youtubeサーチを行うことができます。(事前準備として、Chromeウェブストアで「[yyプラグイン](https://chrome.google.com/webstore/detail/yy%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%83%97%E3%83%A9%E3%82%B9/edooldmlaabbmllldenkkceddlbbeing?hl=ja)」または、「[youtubeプラグイン](https://chrome.google.com/webstore/detail/youtube%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3/mbfpafjmkoefhlkeohddaphbpddmnhmp?hl=ja)」(ともに無料)をインストールしておきます。)ページ内の文字テキストをマウスで選択し、Ctrl+Click(Enterキー)すると、ポップアップメニューが表示されます。そこで、youtubeサーチを選択して実行ボタンを押すと、youtubeサーチがスタートします。この時に、サーチとプレーヤーページのタブがオープンされますが、対策前は、複数ペアのタブが大量に開いていましたが、対策後は、一つのペアのみになりました。

# あとがき
プラグインを作成していて、このタブの多重オープンが発生した時は、驚きました。次から次へとタブが開かれて行き、ブラウザーがタブで一杯になり、早く止めたいと思いましたが止められません。仕方なく、ブラウザーを閉じました。そのうち、メモリ不足が起こり、パソコンが停止してしまうことが想定されました。
このような不具合には驚かされます。毎回、プラグインの初期ロード時は、正常に動作しますが、続けて、youtubeサーチをするとこの多重オープンが発生しました。プラグインのリセットに問題があることは予想できましたが、それがどこに問題があるかがわからず、そのままにしていました。ある時の不具合解決にヒントがありましたが、そのことがなかったら、まだ解決していなかったかもしれません。
もう少し、突っ込んで問題に取り組んでいたらわかったかもしれませんが、その時は問題解決の複雑さが予想されて気がめげていました。
真剣に取り組んでいたら解決できていたかもしれません。
たかが、ひとつのプラグインですが、その作成過程で、いろいろなことを学ばせてもらいました。いい勉強になりました。
テスト x 食事 x 自動化

# テスト x 食事 x 自動化

テスト自動化と食事について

## はじめに

- テストコードとはレシピである

## 本論

- テストコードに沿って実装する
- レシピに沿って料理する
- 成果が自動で反映される(免疫が上がる)

|イメージ|開発|健康|
|-|-|-|
| 手動 | テスト | 食事 |
| 自動 | テストコード | レシピ |
| 成果 | 免疫UP | 免疫UP |

## おわりに

開発も食事も標準化が必要
デプロイ x 運動 x 自動化

# デプロイ x 運動 x 自動化

デプロイ自動化と運動について

## はじめに

- CI/CDとはジム通いである

## 本論

- 製造後、自動でデプロイする(マージ後にCI/CDを回す)
- 仕事後、自動で運動する(仕事帰りにジムへ行く)
- 成果が自動で反映される(代謝が上がる)

|イメージ|開発|健康|
|-|-|-|
| 手動 | デプロイ | 運動 |
| 自動 | CI/CD | ジム通い |
| 成果 | 代謝UP | 代謝UP |

## おわりに

開発も運動も習慣化が必要
ChatGPTでサクッと職場の安全標語を考える！

# 1. はじめに

（できるかと相談を受けたのでやってみました。今回の記事はサクッと短めです）

今回は、多くの職場で出される宿題の一つ「安全標語を考える」を、ChatGPTに手伝ってもらおうと思います！

:::note info
今回取り扱うのは、安全標語ですが、品質標語とか、人権標語ような〇〇標語も同じように使用できると思います。
:::

# 2. プロンプト

使用するプロンプトはこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3130775/511d1872-48f6-15f6-a8d2-16536fa8a9e8.png)

(安全標語の例の引用: http://copper-brass.gr.jp/safety/safe-info/201310-h25anzen)

**ポイント**

* ChatGPTは日本の「安全標語」についてよく知らないのか、詳しく説明してあげると、出力が近いものになりました。
* 出力条件のところに、自分が書きたい安全標語のイメージを追加するとオリジナル要素が出ます。

ChatGPTの回答はこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3130775/558e7c1e-e15c-5f53-764b-767ad1c495cf.png)

リクエスト通り、整理整頓系の標語を作ってくれていますね。

5.の「整理整頓で安全をキープ　トラブルを防ぐクリーンな環境」がいい感じだと思います。

:::note info
英語を翻訳しているのか、ちょっと違和感のある文章がところどころありますが、完全にお任せというよりはちょっと直す前提で見るといいと思います。
:::

ただ全体的に文章がちょっと短い感じがするので、長くしてもらいましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3130775/2dd5de75-7e95-1739-1882-e5a4bb1f9154.png)

個人的には、4.の「一つ一つ丁寧に　整理整頓の心得　安全な現場への道は日々の積み重ねから」とか、8.の「整頓された現場　無事故を目指す　効率アップの鍵は安全と整理整頓の両立」が好きです。

ちょっと言葉を修正したり、気に入った2つのアイデアをくっつけたりして完成です！

# 3. おまけ

タイトルも同じように考えてもらっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3130775/13d56a35-8697-d288-318e-cf144466781b.png)

今回は、7にしました！

:::note warn
（日本のサラリーマンの皆様、聞こえますか...？
こちらの記事は当方のTop3に入るアクセス数のわりに、いいねが全然つきません...
この記事の内容を使って安全標語の作成を楽しちゃった方は、お手持ちのスマホから、Qiitaのアカウントを作って、ぜひともいいねをお願いします...）
:::
.NET MAUIでEditorコントロール利用を諦めてEntryにした理由

## 1. はじめに

.NET MAUIアプリケーション開発において、エディタコントロールは便利で多機能なテキスト入力ウィジェットです。しかし、特定のキーボード操作が求められる場合、その利点が制約となることがあります。この記事では、私がEditorコントロールの使用をやめて、Entryコントロールに切り替えた理由を説明します。

## 2. Editorコントロールでの制約

### 2.1. Ctrl + Enterでの送信が困難

メールやチャットアプリでは、Ctrl + Enterキーでメッセージを送信する機能が一般的です。しかし、Editorコントロールでは、Ctrl + Enterによるイベントの検出が困難でした。.NET MAUIでは、キーボードイベントのハンドリングが限定的です。

### 2.2. タブキーでのフォーカス移動ができない

Editorコントロールでは、タブキーを使用してフォーカスを他のコントロールに移動することができません。これにより、キーボード操作によるフォーカスの移動が制限されます。

## 3. Entryコントロールへの切り替え

これらの制約を克服するために、Editorコントロールの代わりにEntryコントロールを使用することにしました。Entryコントロールを使用することで、フォーカス移動が出来るようになります。

### 3.1. タブキーでのフォーカス移動が可能

Entryコントロールでは、タブキーを使用してフォーカスを他のコントロールに移動することができます。これにより、TABキー押下後にスペースキー押下で、すぐに送信が可能となりました。

### 3.2. 改行が制限される

Entryコントロールは、一行のテキスト入力に特化しており、改行はサポートされていません。ただし、Macでは、なぜかCtrl+Enterで改行が可能であるため、これを利用しています。

## 4. 暫定の見た目

起動→文字入力→送信 をすべてキーボード操作で行うことができるようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335991/89ed4055-5988-6962-4bd8-025eceebcb49.png)


## 5. まとめ

Editorコントロールは多機能で便利ですが、特定のキーボード操作が必要な場合は制約となることがあります。この記事では、.NET MAUIでEditorコントロールの使用をやめて、Entryコントロールに切り替えた理由を説明しました。これにより、タブキーでのフォーカス移動が可能になり、キーボード操作による送信が容易になりました。しかし、改行のサポートが制限されているため、適切な改行方法を検討する必要があります。最終的には、要件に応じて適切なコントロールを選択することが重要です。
オライリーの「Subversionによるバージョン管理」の日本語版 PDF を入手する

## はじめに

オライリーから発行されている「Version Control with Subversion, 2nd Edition」は、どうやら無償で各国語版の PDF 版を入手できるようです（残念ながら、日本語版はかなり古い版しかないようですが。詳細後述）。

日本語版の付録 D についているコピーライトを見ると、[CC BY 2.0](https://creativecommons.org/licenses/by/2.0/) でライセンスされているみたいですね。
つまりライセンス者の名前を付けておけば、複製、再配布、改変が可能というもの。

日本語版の書籍名だと「実用 Subversion 第2版」に当たるのかな？
よくわからないですが、日本で発行された書籍とは別に、英語版（書籍の元になった文書）を翻訳したもののように思います。

（おそらく、[英語版のページ](https://svnbook.red-bean.com/index.en.html) が最初にあって、それがオライリーから[Version Control with Subversion, 2nd Edition](https://www.oreilly.com/library/view/version-control-with/9780596510336/)として出版されて、その日本語訳が [実用 Subversion 第2版](https://www.oreilly.co.jp/books/9784873114149/) になるのだと思いますが、PDF としてダウンロードできるものは書籍とは関係なく [英語版のページ](https://svnbook.red-bean.com/index.en.html) の古い版の有志による日本語訳になのだと思います）

最近ではバージョン管理には Git を使うのが一般的だとは思いますが、たまには Subversion を使うこともあるかもしれませんよね？

## 入手方法

英語版の [Open Books](https://www.oreilly.com/openbook/) のページから「Version Control with Subversion, 2nd Edition」を選ぶと、各言語版の pdf/html などが入手できます。

* [日本語版のページ](https://svnbook.red-bean.com/index.ja.html)
  * [Subversion によるバージョン管理 - for Subversion 1.2](http://jtdan.com/vcs/svn/svn-book.pdf) (PDF) - なぜか http なのでワーニングがでるかも
  * 出版されている日本語版のページ：[実用 Subversion 第2版](https://www.oreilly.co.jp/books/9784873114149/)
* [英語版のページ](https://svnbook.red-bean.com/index.en.html)
  * [Version Control with Subversion - for Subversion 1.7](https://svnbook.red-bean.com/en/1.7/svn-book.pdf) (PDF)
  * 出版されている英語版のページ：[Version Control with Subversion, 2nd Edition](https://www.oreilly.com/library/view/version-control-with/9780596510336/)

各言語版の「for Subversion 1.x」と書いてあるのは、Subversion 本体のバージョンのことのようです。
英語版の PDF は ver 1.7 まで存在しますが（英語の書籍版は ver 1.5 向けだったようなので、それよりも新しい版もある）、それに比べると、日本語版は ver 1.2 のみなので、かなり古いバージョンだけしかないようです。

上記以外にも、各国の言語や、英語版の古いもの等もあります。

## その他

日本のオライリーにも、 [O'Reilly Library](https://www.oreilly.co.jp/library/) としていくつか書籍は公開されている。

参考：

https://qiita.com/yoshi389111/items/eb528625b3423e63828b
windows powershell環境で'python --version'実行時にreturncode=9009が返ってくる


windows powershell環境で'python --version'実行時にreturncode=9009が返ってくる

```
CompletedProcess(args='python --version', returncode=9009, stderr='Python ')
```

パスが通っていない or pythonがインストールできていないとreturncode=9009になりそうである

https://wikiwiki.jp/sd_toshiaki/%E3%82%A8%E3%83%A9%E3%83%BC%E8%A7%A3%E6%B1%BA%E3%83%A1%E3%83%A2

```
> 「Add Python to PATH」にチェックを入れずにPythonをインストールしたらWebUIが起動しない 
> Couldn't launch python
> 
> exit code: 9009
> 
> stderr:
> Python was not found but can be installed from the Microsoft Store: https://go.microsoft.com/fwlink?linkID=2082640
> Launch unsuccessful. Exiting.
> 続行するには何かキーを押してください . . .
```

インストールする or パスを通すことで無事に解決
HackTheBox Appointment Writeup

# はじめに

本記事は「[HackTheBox:Appointment](https://app.hackthebox.com/starting-point)」のwriteupです。

## 問題

SQLインジェクションに関する問題です。

## 回答

とりあえず、ポートスキャンします。
スキャン対象は80(`-p80`)を指定します。
結果`http(tcp/80)`が公開されていることがわかりました。

```text
┌──(kali㉿kali)-[~]
└─$ nmap -sV -p80 10.129.221.168
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-25 23:51 JST
Nmap scan report for 10.129.221.168
Host is up (0.18s latency).

PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.38 ((Debian))

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 9.19 seconds
```

ブラウザからアクセスするとログイン画面が表示されました。

![](https://raw.githubusercontent.com/kenryo012/qiita-content/main/images/HACKTHEBOX_Appointment/1.png)

設問に書いてある通りユーザー名末尾にコメントアウト`#`をつけます。
また、パスワードにSQLインジェクションおなじみの`' or '1'='1`を指定します。
無事ログインできました。

![](https://raw.githubusercontent.com/kenryo012/qiita-content/main/images/HACKTHEBOX_Appointment/2.png)

本文では`Gobuster`について説明がありましたが、何に使うか不明でした。

## 参考

- https://web-scan.jp/article/1868/
- https://github.com/OJ/gobuster
`Ubuntu: no space left on device `と表示されたがディスク容量は余っているなぜ、、と思ったらinodeが足りなかっただけだった際のメモ

表題のメモです

# エラー内容

ある日、`ubuntu`上で作業をしているとこんなエラーメッセージが出ました

```
`Ubuntu: no space left on device `
```


https://serverfault.com/questions/882160/ubuntu-no-space-left-on-device-while-inodes-and-storage-usage-less-than-10

ただのディスク容量かと思いきや、以下を見ても明らかに不足していない（`/`以下に十分な空きがあった）

```
df -h
```

なぜ、、と思ったら`inode`を確認していたらこちらが枯渇していた。

```
df -ih
```

https://itojisan.xyz/trouble/15772/#:~:text=%E3%80%8CNo%20space%20left%20on%20device%E3%80%8D%E3%81%AE%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%AF%E3%80%81%E4%B8%BB,%EF%BC%92%E3%81%A4%E3%81%AE%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82&text=%E3%82%A8%E3%83%A9%E3%83%BC%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%8B%E3%82%89%E3%83%87%E3%82%A3%E3%82%B9%E3%82%AF%E3%81%AE,%E3%81%8C%E9%9D%9E%E5%B8%B8%E3%81%AB%E5%A4%9A%E3%81%84%E3%81%A7%E3%81%99%E3%80%82

> 「No space left on device」のメッセージは、主にLinuxやmacOSで使用する容量が不足した際に発生するエラーです。
> 容量不足が発生する原因として、次の２つのパターンがあります。
> ディスク容量が不足している
> 「inode」の容量が不足している

以下の対策を行った

> 不要なファイルを削除（ログファイルなどが大量であればこれで解決するはず）
> 再起動（tmpfsに大量ファイルがあればこれで解決するはず）
> これでも解決しない場合は他に不要にinodeを使っているものがいないか色々と見直す必要がある

無事に解決、良かった
PostgreSQL　空の行に対してGROUP BYをした場合の関数の返しについて



１行もヒットしない条件の中GROUP BYをしたところ、空の結果が返され
その結果Null PointExceptionが発生してしまった。

```
CREATE TABLE users_table (
  id SERIAL PRIMARY KEY,
  name VARCHAR(20)
)


INSERT INTO users_table (name) VALUES ('BOB'),('KEN'), (NULL)
```

上記のデータに

```
    SQL① 1行もヒットしない条件に対してGROUP BYをする。
SELECT count(name) AS count FROM users_table WHERE name = 'JOB' GROUP BY name

count
row0
 ```
とすると空の結果が返される

```
SQL② GROUP BYをしない。
SELECT count(name) AS count FROM users_table WHERE name = 'JOB' 

count |
1     | row1
 ```


GROUP BYすることによってかえってくる結果が変わるらしい。


SQL①はGROUP BYをしているが’JOB’が存在しないためグループ化する対象がないため、結果として何も返されない。


②はそもそもGROUP化をしていないため、テーブル全体が単一のグループとして扱われて、nameが'JOB'である行の数をカウントされているため0が返される。

GROUP BYを使用する際には気を付けます。