Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SQL Tutorial

nrs
June 14, 2019

SQL Tutorial

グループ合同の新卒研修で行った SQL 入門向けの解説 + ワークショップです。
基本的な部分の解説のみで、一部触れていない構文もございます。
ご了承ください。

KKK: 価格, TNK: 単価, MST: マスタ, IDX: インデックス

# URL
HomePage: https://nrslib.com
Twitter: https://twitter.com/nrslib

nrs

June 14, 2019
Tweet

More Decks by nrs

Other Decks in Programming

Transcript

  1. 11

  2. 12

  3. 29

  4. SELECT * FROM world WHERE name = 'Japan' name が

    ‘Japan’ のレコードを取得 53
  5. SELECT * FROM world WHERE name = 'Japan' area が

    377930 より大きい国を探す 55
  6. SELECT * FROM world WHERE area > 377930 area が

    377930 より大きいレコードを取得 57
  7. SELECT * FROM world WHERE name = 'Japan' area が

    377930 より大きい かつ 人口が 127,090,000 人より 多い国 61
  8. SELECT * FROM world WHERE area > 377930 AND population

    > 127090000 area が 377,930 より大きい 66
  9. SELECT * FROM world WHERE area > 377930 AND population

    > 127090000 area が 377,930 より大きい かつ 67
  10. SELECT * FROM world WHERE area > 377930 AND population

    > 127090000 area が 377,930 より大きい かつ population が 127,090,000 より大きい 68
  11. Exercise 3 : 条件指定 SQLZOO: 0 SELECT basics 面積か人口の数字が 日本以下の国を取得しよう

    SELECT * FROM world WHERE area > 377930 AND population > 127090000 Sample 70
  12. SELECT * FROM world WHERE area > 377930 AND population

    > 127090000 ORDER BY gdp SELECT * FROM world WHERE area < 377930 AND population < 127090000 ORDER BY gdp DESC 77
  13. SELECT * FROM world WHERE area > 377930 AND population

    > 127090000 ORDER BY gdp SELECT * FROM world WHERE area < 377930 AND population < 127090000 ORDER BY gdp DESC 昇順 78
  14. SELECT * FROM world WHERE area > 377930 AND population

    > 127090000 ORDER BY gdp SELECT * FROM world WHERE area < 377930 AND population < 127090000 ORDER BY gdp DESC 降順 79
  15. SELECT * FROM world ORDER BY gdp DESC, area, population

    DESC ソートするカラムは複数指定できる 80
  16. SELECT * FROM world WHERE area > 377930 AND population

    > 127090000 ORDER BY gdp 人口変わったらどうしよう 86
  17. SELECT * FROM world WHERE area > 377930 AND population

    > ( SELECT population FROM WORLD WHERE name = 'Japan' ) ORDER BY gdp SELECT * FROM world WHERE area > 377930 AND population > 127090000 ORDER BY gdp 88
  18. SELECT * FROM world WHERE area > 377930 AND population

    > ( SELECT population FROM world ) ORDER BY gdp 副問い合わせが 複数行の結果になるとエラー 89
  19. Exercise 5 : 副問い合わせ SQLZOO: 0 SELECT basics 面積も副問い合わせを利用するようにしよう SELECT

    * FROM world WHERE area > 377930 AND population > ( SELECT population FROM WORLD WHERE name = 'Japan' ) ORDER BY gdp 90
  20. SELECT * FROM world WHERE name LIKE 'J%'; SELECT *

    FROM world WHERE name LIKE '%n'; SELECT * FROM world WHERE name LIKE 'J%n'; 99
  21. SELECT * FROM world WHERE name LIKE 'J%'; SELECT *

    FROM world WHERE name LIKE '%n'; SELECT * FROM world WHERE name LIKE 'J%n'; クエリの区切りはセミコロン 100
  22. SELECT * FROM world WHERE name LIKE 'J%'; SELECT *

    FROM world WHERE name LIKE '%n'; SELECT * FROM world WHERE name LIKE 'J%n'; ‘J’ からはじまる 101
  23. SELECT * FROM world WHERE name LIKE 'J%'; SELECT *

    FROM world WHERE name LIKE '%n'; SELECT * FROM world WHERE name LIKE 'J%n'; ‘n’ で終わる 102
  24. SELECT * FROM world WHERE name LIKE 'J%'; SELECT *

    FROM world WHERE name LIKE '%n'; SELECT * FROM world WHERE name LIKE 'J%n'; ‘J’ で始まり ‘n’ で終わる 103
  25. SELECT * FROM world WHERE name LIKE 'J%'; SELECT *

    FROM world WHERE name LIKE '%n'; SELECT * FROM world WHERE name LIKE 'J%n'; 111
  26. SELECT * FROM world WHERE name LIKE 'J%'; SELECT *

    FROM world WHERE name LIKE '%n'; SELECT * FROM world WHERE name LIKE 'J%n'; インデックスが効く 112
  27. SELECT * FROM world WHERE name LIKE 'J%'; SELECT *

    FROM world WHERE name LIKE '%n'; SELECT * FROM world WHERE name LIKE 'J%n'; インデックスが効かない 113
  28. SELECT * FROM world WHERE name LIKE 'J%'; SELECT *

    FROM world WHERE name LIKE '%n'; SELECT * FROM world WHERE name LIKE 'J%n'; インデックスが前方だけ効く 114
  29. Exercise 6 : あいまい検索 SQLZOO: 0 SELECT basics 国名に ‘a’

    が2文字以上存在する国の中で もっとも gdp が高い国を探そう 119
  30. 126 SELECT * FROM world WHERE population IN ( SELECT

    population FROM world WHERE name = 'Japan' ) IN ならサブクエリの結果が 複数行でも OK (このクエリ自体は微妙)
  31. 138

  32. 140

  33. 143

  34. SELECT * FROM game JOIN eteam ON game.team1 = eteam.id

    JOIN eteam ON game.team2 = eteam.id 145
  35. SELECT * FROM game JOIN eteam ON game.team1 = eteam.id

    JOIN eteam ON game.team2 = eteam.id 146
  36. SELECT * FROM game JOIN eteam ON game.team1 = eteam.id

    JOIN eteam ON game.team2 = eteam.id 147
  37. SELECT * FROM game JOIN eteam eteam1 ON game.team1 =

    eteam1.id JOIN eteam eteam2 ON game.team2 = eteam2.id 148
  38. SELECT * FROM game JOIN eteam eteam1 ON game.team1 =

    eteam1.id JOIN eteam eteam2 ON game.team2 = eteam2.id エイリアス(別名) 149
  39. SELECT * FROM game JOIN eteam eteam1 ON game.team1 =

    eteam1.id JOIN eteam eteam2 ON game.team2 = eteam2.id 150
  40. SELECT * FROM game JOIN eteam eteam1 ON game.team1 =

    eteam1.id JOIN eteam eteam2 ON game.team2 = eteam2.id 151
  41. SELECT * FROM game JOIN eteam eteam1 ON game.team1 =

    eteam1.id JOIN eteam eteam2 ON game.team2 = eteam2.id 二重にデータが取れてるし そもそも正式名称あるから いらないよね 152
  42. SELECT game.id, game.mdate, game.stadium, eteam1.teamname, eteam1.coach, eteam2.teamname, eteam2.coach FROM game

    JOIN eteam eteam1 ON game.team1 = eteam1.id JOIN eteam eteam2 ON game.team2 = eteam2.id 153
  43. SELECT g.id, g.mdate, g.stadium, t1.teamname, t1.coach, t2.teamname, t2.coach FROM game

    g JOIN eteam t1 ON game.team1 = t1.id JOIN eteam t2 ON game.team2 = t2.id 155
  44. SELECT game.id, game.mdate, game.stadium, eteam1.teamname, eteam1.coach, eteam2.teamname, eteam2.coach SELECT g.id,

    g.mdate, g.stadium, t1.teamname, t1.coach, t2.teamname, t2.coach 省略形は脳内スタックを消費する 160
  45. Exercise 9 : テーブルを結合しよう SQLZOO: 6 JOIN goal テーブルと eteam

    テーブルを結合しよう SELECT * FROM game JOIN eteam eteam1 ON game.team1 = eteam1.id JOIN eteam eteam2 ON game.team2 = eteam2.id Sample 166
  46. id name division 1 John 1 2 Jane 2 3

    Naruse 3 id name 1 Customer Support 2 System partners divisions 170
  47. id name division 1 John 1 2 Jane 2 3

    Naruse 3 id name 1 Customer Support 2 System partners divisions SELECT * FROM partners JOIN divisions ON partners.division = divisions.id 171
  48. id name division 1 John 1 2 Jane 2 3

    Naruse 3 id name 1 Customer Support 2 System partners divisions SELECT * FROM partners JOIN divisions ON partners.division = divisions.id partners.id partners.name partners.division divisions.id divisions.name 1 John 1 1 Customer Support 2 Jane 2 2 System 172
  49. id name division 1 John 1 2 Jane 2 3

    Naruse 3 id name 1 Customer Support 2 System partners divisions SELECT * FROM partners LEFT OUTER JOIN divisions ON partners.division = divisions.id 173
  50. id name division 1 John 1 2 Jane 2 3

    Naruse 3 id name 1 Customer Support 2 System partners divisions SELECT * FROM partners LEFT OUTER JOIN divisions ON partners.division = divisions.id 174
  51. id name division 1 John 1 2 Jane 2 3

    Naruse 3 id name 1 Customer Support 2 System partners divisions partners.id partners.name partners.division divisions.id divisions.name 1 John 1 1 Customer Support 2 Jane 2 2 System 3 Naruse 3 NULL NULL SELECT * FROM partners LEFT OUTER JOIN divisions ON partners.division = divisions.id 175
  52. 188

  53. CREATE TABLE world ( name VARCHAR(20), continent VARCHAR(20), area INTEGER,

    population INTEGER, gdp INTEGER, capital VARCHAR(20), tld VARCHAR(4) ) 189
  54. CREATE TABLE world ( name VARCHAR(20), continent VARCHAR(20), area INTEGER,

    population INTEGER, gdp INTEGER, capital VARCHAR(20), tld VARCHAR(4) ) 190
  55. CREATE TABLE world ( name VARCHAR(20), continent VARCHAR(20), area INTEGER,

    population INTEGER, gdp INTEGER, capital VARCHAR(20), tld VARCHAR(4) ) カラムの宣言 191
  56. CREATE TABLE world ( name VARCHAR(20), continent VARCHAR(20), area INTEGER,

    population INTEGER, gdp INTEGER, capital VARCHAR(20), tld VARCHAR(4) ) カラムの型 VARCHAR は可変長な文字列 192
  57. CREATE TABLE world ( name VARCHAR(20), continent VARCHAR(20), area INTEGER,

    population INTEGER, gdp INTEGER, capital VARCHAR(20), tld VARCHAR(4) ) カラムの型 VARCHAR は可変長な文字列 データベースによって方言があるので注意 193
  58. 196

  59. INSERT INTO world VALUES ( 'Pakistan', 'Asia', 881912, 188020000, 215117000000,

    'Islamabad', '.pk') INSERT INTO world VALUES ( 'Pakistan', 'Asia', 881912, 188020000, 215117000000, 'Islamabad') tld 入れ忘れた! 200
  60. INSERT INTO world VALUES ( 'Pakistan', 'Asia', 881912, 188020000, 215117000000,

    'Islamabad', '.pk') INSERT INTO world VALUES ( 'Pakistan', 'Asia', 881912, 188020000, 215117000000, 'Islamabad') tld 入れ忘れた! NULL 201
  61. INSERT INTO world VALUES ( 'Pakistan', 'Asia', 881912, 188020000, 215117000000,

    'Islamabad', '.pk') INSERT INTO world VALUES ( 'Pakistan', 'Asia', 881912, 188020000, 215117000000, 'Islamabad') tld 入れ忘れた! NULL 防ぎたい 202
  62. CREATE TABLE world ( name VARCHAR(20) NOT NULL, continent VARCHAR(20)

    NOT NULL, area INTEGER NOT NULL, population INTEGER NOT NULL, gdp INTEGER NOT NULL, capital VARCHAR(20) NOT NULL, tld VARCHAR(4) NOT NULL ) 203
  63. CREATE TABLE world ( name VARCHAR(20) NOT NULL, continent VARCHAR(20)

    NOT NULL, area INTEGER NOT NULL, population INTEGER NOT NULL, gdp INTEGER NOT NULL, capital VARCHAR(20) NOT NULL, tld VARCHAR(4) NOT NULL ) 204
  64. 205

  65. INSERT INTO world VALUES ( 'Pakistan', 'Asia', 881912, 188020000, 215117000000,

    'Islamabad', '.pk') INSERT INTO world VALUES ( 'Pakistan', 'Asia', 881912, 188020000, 215117000000, 'Islamabad', '.pk') 207
  66. INSERT INTO world VALUES ( 'Pakistan', 'Asia', 881912, 188020000, 215117000000,

    'Islamabad', '.pk') INSERT INTO world VALUES ( 'Pakistan', 'Asia', 881912, 188020000, 215117000000, 'Islamabad', '.pk') 間違えて Pakistan がふたつ! 208
  67. INSERT INTO world VALUES ( 'Pakistan', 'Asia', 881912, 188020000, 215117000000,

    'Islamabad', '.pk') INSERT INTO world VALUES ( 'Pakistan', 'Asia', 881912, 188020000, 215117000000, 'Islamabad', '.pk') 間違えて Pakistan がふたつ! 防ぎたい 209
  68. CREATE TABLE world ( name VARCHAR(20) UNIQUE, continent VARCHAR(20) NOT

    NULL, area INTEGER NOT NULL, population INTEGER NOT NULL, gdp INTEGER NOT NULL, capital VARCHAR(20) NOT NULL, tld VARCHAR(4) NOT NULL ) 210
  69. CREATE TABLE world ( name VARCHAR(20) UNIQUE, continent VARCHAR(20) NOT

    NULL, area INTEGER NOT NULL, population INTEGER NOT NULL, gdp INTEGER NOT NULL, capital VARCHAR(20) NOT NULL, tld VARCHAR(4) NOT NULL ) 211
  70. id Name 1 John Doe 2 Jane Doe 3 John

    Doe ソフトウェアシステムでも 見分けがつく 225
  71. CREATE TABLE user ( id INTEGER PRIMARY KEY, name VARCHAR(20)

    NOT NULL ) id = Identity(同一性) 227
  72. CREATE TABLE user ( id INTEGER PRIMARY KEY, name VARCHAR(20)

    NOT NULL ) PRIMARY KEY 制約は一意であることを保証する 228
  73. CREATE TABLE user ( id INTEGER PRIMARY KEY, name VARCHAR(20)

    NOT NULL ) PRIMARY KEY 制約は一意であることを保証する (NOT NULL かつ UNIQUE) 229
  74. SELECT * FROM users WHERE users.id = 'naruse' AND users.password

    = 'password' これでレコード読めたら OK 238
  75. SELECT * FROM users WHERE users.id = 'naruse' AND users.password

    = 'password' ここはユーザの入力 239
  76. SELECT * FROM users WHERE users.id = 'naruse' AND users.password

    = 'password' ID: naruse PASS: password 242
  77. SELECT * FROM users WHERE users.id = '' AND users.password

    = '' ID: naruse PASS: ‘ OR ‘a’ = ‘a 243
  78. SELECT * FROM users WHERE users.id = '' users.password =

    '' ID: naruse PASS: ‘ OR ‘a’ = ‘a SELECT * FROM users WHERE users.id = 'naruse’ AND users.password = '' OR 'a' = 'a' 244
  79. SELECT * FROM users WHERE users.id = '' users.password =

    '' ID: naruse PASS: ‘ OR ‘a’ = ‘a 245 SELECT * FROM users WHERE users.id = 'naruse’ AND users.password = '' OR 'a' = 'a' アタック成功
  80. OOP RDB Employee Name Age Division Position name age division

    position Jane 22 1 1 id name 1 System Division employees divisions 260
  81. OOP RDB Employee Name Age Division Position name age division

    position Jane 22 1 1 id name 1 System Division id name 1 Partner employees divisions positions 261
  82. OOP RDB Employee Name Age Division Position name age division

    position Jane 22 1 1 id name 1 System Division id name 1 Partner employees divisions positions O/R Mapper 262
  83. public class MyDbContext : DbContext { public DbSet<User> Users {

    get; set; } } public class User { public string Id { get; set; } public string Name { get; set; } } 263
  84. public class MyDbContext : DbContext { public DbSet<User> Users {

    get; set; } } public class User { public string Id { get; set; } public string Name { get; set; } } using (var context = new MyDbContext()) { var user = context.Users.Where(x => x.Name == "naruse"); ... } 264
  85. public class MyDbContext : DbContext { public DbSet<User> Users {

    get; set; } } public class User { public string Id { get; set; } public string Name { get; set; } } using (var context = new MyDbContext()) { var user = context.Users.Where(x => x.Name == "naruse"); ... } SELECT * FROM users WHERE namee = 'naruse' 265
  86. public class MyDbContext : DbContext { public DbSet<User> Users {

    get; set; } } public class User { public string Id { get; set; } public string Name { get; set; } } using (var context = new MyDbContext()) { var user = context.Users.Where(x => x.Name == "naruse"); ... } SELECT * FROM users WHERE namee = 'naruse' SQL が生成されて 実行される 266
  87. 281

  88. id product awesome del 1 101 <item id=‘1’ num=‘10’ date=‘…

    0 2 101 <item id=‘7’ num=‘15’ date=‘… 0 3 102 <item id=‘3’ num=‘5’ date=‘… 0 283
  89. id product awesome del 1 101 <item id=‘1’ num=‘10’ date=‘…

    0 2 101 <item id=‘7’ num=‘15’ date=‘… 0 3 102 <item id=‘3’ num=‘5’ date=‘… 0 : : というデータが数万件 284
  90. id product awesome del 1 101 <item id=‘1’ num=‘10’ date=‘…

    0 2 101 <item id=‘7’ num=‘15’ date=‘… 0 3 102 <item id=‘3’ num=‘5’ date=‘… 0 : : というデータが数万件 SELECT * FROM orders WHERE awesome LIKE '%id=¥'5¥'%' 285
  91. id product awesome del 1 101 <item id=‘1’ num=‘10’ date=‘…

    0 2 101 <item id=‘7’ num=‘15’ date=‘… 0 3 102 <item id=‘3’ num=‘5’ date=‘… 0 : : というデータが数万件 SELECT * FROM orders WHERE awesome LIKE '%id=¥'5¥'%' どうしてこうなったか 286