SELECT
C1.社員コード, C1.資格 AS 資格1, C2.資格 AS 資格2
FROM
社員取得資格 C1
LEFT OUTER JOIN 社員取得資格 C2
[ a ]
この問題の正解は、
SELECT
C1.社員コード, C1.資格 AS 資格1, C2.資格 AS 資格2
FROM
社員取得資格 C1
LEFT OUTER JOIN 社員取得資格 C2
ON C1.社員コード = C2.社員コード
AND C1.資格 = 'FE' AND C2.資格 = 'AP'
WHERE
C1.資格 = 'FE'
になりますが、不正解の選択肢と共通している字句は
ON C1.社員コード = C2.社員コード
AND C1.資格 = 'FE' AND C2.資格 = 'AP'
で、自己結合のために使用するC1.社員コード = C2.社員コード以外にC1.資格 = 'FE' AND C2.資格 = 'AP'という条件があるようです。
ON句の条件が結果にどのように影響するのか
ON句に結合条件以外を指定するとどのように振る舞うのかを確認してみたいと思います。
自己結合すると何が得られるのか
まずは、社員コードで自己結合すると何が得られるかを確認してみましょう。
SELECT
C1.社員コード, C1.資格 AS 資格1, C2.資格 AS 資格2
FROM
社員取得資格 C1
LEFT OUTER JOIN 社員取得資格 C2
ON C1.社員コード = C2.社員コード
SELECT
C1.社員コード, C1.資格 AS 資格1, C2.資格 AS 資格2
FROM
社員取得資格 C1
LEFT OUTER JOIN 社員取得資格 C2
ON C1.社員コード = C2.社員コード
AND C1.資格 = 'FE'
AND C2.資格 = 'AP'
WHERE
C1.資格 = 'FE'
SELECT
C1.社員コード,
C1.資格 AS 資格1,
CASE
WHEN EXISTS (SELECT 1 FROM 社員取得資格 C2 WHERE C1.社員コード = C2.社員コード AND C2.資格 = 'AP') THEN 'AP'
ELSE NULL
END AS 資格2
FROM
社員取得資格 C1
WHERE
C1.資格 = 'FE'
$ mkdir bun-demo
$ cd bun-demo
$ bun init
bun init helps you get started with a minimal project and tries to guess sensible defaults. Press ^C anytime to quit
package name (bun-demo):
entry point (index.ts): src/index.ts
Done! A package.json file was saved in the current directory.
+ index.ts
+ .gitignore
+ tsconfig.json (for editor auto-complete)
+ README.md
To get started, run:
bun run index.ts
import { expect, test } from "bun:test";
import { greet } from "../src/greet";
test("should return hello world", () => {
expect(greet("world")).toBe("Hello, world!");
});
テストはbun testコマンドで実行可能です。
$ bun test
bun test v1.1.7 (b0b7db5c)
test/greet.spec.ts:
✓ should return hello world [0.41ms]
1 pass
0 fail
1 expect() calls
Ran 1 tests across 1 files. [57.00ms]
$ z foo
$ mkdir -p bar/baz
$ mkdir -p abc/def
# foo/bar/bazディレクトリに移動する
$ z bar/baz
# 直前にいたfooディレクトリに戻る
$ z -
# 移動したことのあるbazディレクトリに直接移動する
$ z baz
$ z -
$ z abc/def
# 移動したことがあるなら直前にいたディレクトリでなくても移動可能
$ z baz
$ z def
$ brew install cheat
# コマンドを始めて調べるときはコミュニティ提供のチートシートをダウンロードできる
$ cheat sort
A config file was not found. Would you like to create one now? [Y/n]: y
Would you like to download the community cheatsheets? [Y/n]: y
Cloning community cheatsheets to /Users/t0k0sh1/.config/cheat/cheatsheets/community.
Enumerating objects: 335, done.
Counting objects: 100% (335/335), done.
Compressing objects: 100% (310/310), done.
Total 335 (delta 43), reused 213 (delta 23), pack-reused 0
Cloning personal cheatsheets to /Users/t0k0sh1/.config/cheat/cheatsheets/personal.
Created config file: /Users/t0k0sh1/.config/cheat/conf.yml
Please read this file for advanced configuration information.
# 以降はチートシートを表示する
# To sort a file:
sort <file>
# To sort a file by keeping only unique:
sort -u <file>
# To sort a file and reverse the result:
sort -r <file>
# To sort a file randomly:
sort -R <file>
# To sort a file and store the output in another file:
sort <inputFile> -o <outputFile>
# Sort by default uses /var/tmp to store temp files but size of /var/tmp directory is limited. In order to sort huge use a directory with adequate size:
sort -T <tempDirectory> <file>
# 一度ローカルに保存したチートシートは編集できる
$ cheat -e sort
@Component
public class MyService {
private final DependencyClass dependency;
@Autowired
public MyService(DependencyClass dependency) {
this.dependency = dependency;
}
}
のように書きます。
コンストラクタインジェクションが推奨される理由
Spring Framework でコンストラクタインジェクションが推奨される理由のうち、特に理由としてふさわしいと思ったものには以下が2つがあります。
INSERT INTO sales_by_product
SELECT
T1.product_code,
0 total_sales_amount
FROM
products T1
WHERE
NOT EXISTS (
SELECT
1
FROM
sales_by_product T2
WHERE
T1.product_code = T2.product_code
);
INSERTするテーブルのカラムと同じカラムを抽出する
SELECTではINSERTするテーブルと同じカラムを抽出します。
SELECT
T1.product_code,
0 total_sales_amount
FROM
products T1
SELECT
T1.product_code,
0 total_sales_amount
FROM
products T1
WHERE
NOT EXISTS (
SELECT
1
FROM
sales_by_product T2
WHERE
T1.product_code = T2.product_code
);
まずは、INSERT前の商品別売上実績テーブルを確認してみます。
SELECT * FROM sales_by_product;
=>
S001,50
S003,250
S004,350
S006,450
SELECT
T1.product_code,
0 total_sales_amount
FROM
products T1
WHERE
NOT EXISTS (
SELECT
1
FROM
sales_by_product T2
WHERE
T1.product_code = T2.product_code
);
=>
S002,0
S005,0
問題なさそうです。
では実際にINSERTまでやって、再度全件抽出してみます。
INSERT INTO sales_by_product
SELECT
T1.product_code,
0 total_sales_amount
FROM
products T1
WHERE
NOT EXISTS (
SELECT
1
FROM
sales_by_product T2
WHERE
T1.product_code = T2.product_code
);
SELECT * FROM sales_by_product;
=>
S001,50
S002,0
S003,250
S004,350
S005,0
S006,450
INSERTしたい結果を抽出できるSELECT文を書いて、その前にINSERT INTO テーブル名を付けるということを覚えておけば、それほど悩むこともないと思います。細かい点を抜きにすればUPDATE SELECTとは異なり、RDBMSによって構文が変わるということもないので、どれかのRDBMSでやり方を覚えておけば他のRDBMSでもほぼそのまま適用できます。