TECH EXPERT 21日目

TECH::EXPERT

今日はペースアップして頑張ります。
SQL周りの話だったのでサクサク。railsのactiveRecordでSQL文を少し齧ったから理解が早い。改めて思うがActiveRecordは便利なんだけど、勝手な処理に変換するのでわかりづらい。

DB周りに関しても特につまづくことなく理解した。投資やってたり、家計簿つけてたりでデータに関して多少の知識はあったからかな。今後は実装に入っていくので楽しくペースアップできたらいいな。
先輩からteratailというものがあると聞いたので早速登録してみた。
正直TECHのメンターに聞くよりよっぽど有意義な意見交換ができそう。メンターさんはカリキュラム特化な印象(応用に入ってからはほとんど利用してないけど)。

ruby

for文

doは省略可能。
実行される内容にeachが走るので、指定するオブジェクトはeachを使えるオブジェクトのみ。

for 変数 in オブジェクト do
  実行する処理
end
for num in 0..99 do
  puts num
end

map

ハッシュに対しても使える。
その場合も返り値はハッシュではなく配列になる。

hogehoge = {id: 5, price: 10}

hogehoge.map { |key, value| [key, value * 2] } 
=> [[:id, 10], [:price, 20]]

hogehoge.map { |key, value| [key, value * 2] }.to_h
=> {:id=>10, :price=>20}
map { |key, value| value}
valueだけ取り出した配列が返る。

to_h

ハッシュに変換してくれる

.methods と .methods(:メソッド名).owner

使えるメソッドの一覧を取得。
.ownerでそのメソッドの定義元を確認できる。

a = 5
=> 5

irb> a.methods
=> [:-@, :**, :<=>, :upto, :<<, :<=, :>=, :==, :chr, :===, :>>, :[], :to_int, :coerce, :divmod, :to_s, :to_i, :fdiv, :modulo, :remainder, :abs, :magnitude, :gcd, :integer?, :gcdlcm, :numerator, :lcm, :to_r, :floor, :ceil, :round, :truncate, :rationalize, :to_f, :^, :odd?, :even?, :phase, :imag, :abs2, :arg, :conjugate, :conj, :rectangular]

irb> a.method(:even?).owner
=> Integer

SQL

文末は必ず「;」で終わる。
打ち忘れた場合は改行後に;を打ってenterでOK。

SQL(Structured Query Language)はリレーショナルデータベース(RDB)の操作を行うための言語。

命令は大きく2つ、
データを定義するDDL(Data Definition Language)
データを操作するDML(Data Manipulation Language)

DDLの出来ること

命令機能
CREATEデータベースやテーブルの作成
ALTERデータベースやテーブルの更新
DROPデータベースやテーブルの削除

 
・DMLの出来ること

命令機能
INSERTデータの登録
UPDATEデータの更新
DELETEデータの削除
SELECTデータの検索

DB/Tableの操作

terminal

mysqlに接続
なおmysqlを抜ける場合はexit

mysql -u root

データベースを表示

show databases;

CREATE DATABASE文

データベースを作る

CREATE DATABASE データベース名;

USE文

データベースを選択する

USE データベース名;

SHOW TABLES文

選択したデータベースに存在するテーブルを一覧で表示する

SHOW TABLES;

CREATE TABLE文

テーブルを作成する

CREATE TABLE テーブル名 (カラム名 カラム名の型, ……);

mysqlで数字型や文字列型を定義する際は以下のような型名を使用する。

型名保存できる値
INT数字
VARCHAR(M)最大M文字の文字列
CREATE TABLE goods (id INT, name VARCHAR(255));

SHOW COLUMNS FROM

テーブルのカラムを表示する。

SHOW columns FROM テーブル名;

ALTER TABLE

カラムの追加

ALTER TABLE テーブル名 ADD カラム名 カラムの型;
ALTER TABLE テーブル名 ADD (カラム名 カラムの型, ……);

カラム名や型の変更

ALTER TABLE テーブル名 CHANGE 古いカラム名 新しいカラム名 新しいカラムの型;

この際、名前の変更のみをする場合でも型は入力しなければならない。

カラムの削除

ALTER TABLE テーブル名 DROP カラム名;

データの操作

INSERT文

全てのカラムに値を入れる場合

INSERT INTO テーブル名 VALUES(値1, 値2, 値3);

特定のカラムのみに値を入れる場合

INSERT INTO テーブル名(カラム名1, カラム名2) VALUES(値1, 値2);

データの取得

SELECT * FROM テーブル名;

UPDATE文

値の変更

UPDATE テーブル名 SET 変更内容 WHERE 条件;
例
UPDATE goods SET price = 100 WHERE id = 2;

DELETE文

DELETE FROM テーブル名 WHERE 条件;

データの検索

*

ワイルドカード

FROM句

テーブルを選択

FROM テーブル名

SELECT句

SELECT カラム名

WHERE句

WHERE 条件
例
WHERE id = 1
WHERE family_name = "ほげほげ"
WHERE id <= 8

演算子

AND演算子

A かつ B

WHERE a AND b

OR演算子

A または B

WHERE a OR b

NOT演算子

A ではない

WHERE NOT a

BETWEEN演算子

WHERE カラム名 BETWEEN 下限 AND 上限
例
WHERE age BETWEEN 20 AND 30

IN演算子

リストを指定し、カラムの値がそのリストに含まれるときにtrue

WHERE カラム名 IN (値1, 値2, ……)
例
WHERE prefecture IN ("東京都", "神奈川県")

関数

CONCAT関数

concatenateの略。意味は鎖状に繋ぐ。
転じて、複数の文字列を結合できる。
nullが含まれる場合、結合した文字列はnullとなる。

CONCAT(文字列1, 文字列2, ……)
例
SELECT CONCAT(family_name, first_name)
FROM users

AS句

SELECT句でデータを取得する時に、AS句を併用するとカラムに別名を付けられる。

SELECT 取得するデータ AS 別名
例
SELECT CONCAT(family_name, first_name) AS fullname
FROM users

ASは省略できるため、実際にはselectに続けて表記したいカラム名を書く。

SELECT CONCAT(family_name, first_name) "名前"

DISTINCTキーワード

指定したカラムの値が重複する行を除外してデータを取得できる。
distinct 違う、はっきり異なる。

SELECT DISTINCT カラム名
例
SELECT DISTINCT user_id
FROM shifts
WHERE date = "2015-07-01"

GROUP BY句

同じ値を持つデータを1つのグループとしてまとめる。
distinctと異なり、グルーピングしているだけなのでグルーピング内のデータも保持しているため、グループ内のデータ処理も可能。

GROUP BY カラム名

COUNT関数

カラムを指定して使用し、値がnullでないデータの行数を取得する。

SELECT COUNT(カラム名)

カラム名にワイルドカードを指定すれば、nullを含む全レコードの件数を取得する。

SELECT COUNT(*)

AVG関数

MAX関数

MIN関数

テーブルの結合

inner joinとouter join

outer joinは優先テーブルを指定する。
優先テーブルに指定されたテーブル内の要素は全て出力され、対応するjoin先の項目がなければnullが入る。
FROM users JOIN reviews
の左か右のどちらのテーブルを指定するかで、left join/ right joinがある。

inner joinは優先テーブルを考慮しない。
考慮しないため、項目の少ないテーブルに項目数の多いテーブルをjoinした場合、項目数の多いテーブルに合わせてテーブル内容がコピーされてデータ数が増える。
この際、結合先がnullのデータは無視される。

以下のようなテーブルを結合した場合
users id name
1 aa
2 bb
reviews id text user_id
1 ttt 1
2 yyy 1
3 uuu 3

FROM users JOIN reviews ON users.id = reviews.user_id

users id name r.id r.text r.user_id
1 aa 1 ttt 1
1 aa 2 yyy 1

JOIN

無記名のjoinは常にinner joinを示す。
指定したそれぞれのテーブルの、カラムの値が一致するデータを結合できる。
JOIN句はFROM句のあとに記述し、結合の対象となるテーブルを指定する。

FROM テーブル名1
JOIN テーブル名2 ON テーブル名1.カラム名1 = テーブル名2.カラム名2

サブクエリ

ある検索結果を使用して別のSQL文を実行する仕組み

SELECT *
FROM users
WHERE id NOT IN (
    SELECT DISTINCT user_id
    FROM shifts
    WHERE date = "2015-07-01"
)

database総論

キー

  • 主キー
  • 外部キー

制約

  • NOT NULL制約
  • 一意性制約
  • 主キー制約
  • 外部キー制約

null制約

migrationファイルでnull制約をかける。

t.string :name, null: false

一意性制約

migrationファイルにadd_indexでuniqueにする。

class AddEmailToUsers < ActiveRecord::Migration
  def change
    add_column :users, :email, :string
    add_index :users, :email, unique: true
  end
end

主キー制約

not null制約と一意性制約を同時にかけるのと同義。
もともとid行として設定されている。

外部キー制約

外部キーに対応するレコードが必ず存在することを保証する制約
t.references :user, foreign_key: trueとすることでuser_idがカラムに追加され、外部キーとして設定される。

class CreateScores < ActiveRecord::Migration
  def change
    create_table :scores do |t|
      t.string :name
      t.integer :score
      t.references :user, foreign_key: true
      t.timestamps null: false
    end
  end
end

インデックス

カラムに対して設定する。検索の高速化を目的に行う。
以下のデメリットがあるため、インデックスを貼るのは必要最低限で。

  • データを保存・更新する速度が遅くなる
  • データベースの容量を使う
class AddIndexToテーブル名 < ActiveRecord::Migration
  def change
    add_index :テーブル名, :カラム名
  end
end
複数のカラムに貼る場合は
add_index :テーブル名, [:カラム名, :カラム名]

複数のカラムに対してインデックスを貼った場合は、この2種を同時に用いた検索の時に処理が早くなる。言い換えると、カラム単独の検索を行ってもインデックスがないので早くない。

has_many throughオプション

through: :photos_tags 両方ともシンボル
多対多を解消する際に用いる。
顧客ー注文ー商品のようなテーブル構造にした際、連携するテーブルと中継テーブルをhas_manyで連携し、なおかつ中継テーブルはthroughオプションを使う。

# app/models/photo.rb
class Photo < ActiveRecord::Base
  has_many :photos_tags
  has_many :tags, through: :photos_tags
end

# app/models/tag.rb
class Tag < ActiveRecord::Base
  has_many :photos_tags
  has_many :photos, through: :photos_tags
end

# app/models/photos_tag.rb
class PhotosTag < ActiveRecord::Base
  belongs_to :photo
  belongs_to :tag
end
オプション名用途
class_name関連するモデルのクラス名を指定でき、関連名(photos_tags等、has_manyの直後に書くもの)と参照先のクラス名(PhotosTagのようなモデル名)を異なるものにできる
foreign_key参照先を参照する外部キーの名前を指定できる(デフォルトは、参照先のモデル名_id)
dependent親モデルのデータを消したら関連するモデルのデータも連動して消したいときに使用します。destroyとdelete_allでひとつひとつ消していくか、一気に消すかを指定できる
source関連テーブルから先のモデルにアクセスするための(関連モデルから見た)関連名を指定できる

README

マークダウンで記述され、ソフトウェアの仕様、規格、インストール方法などを文書化したもの。rails newをした際に自動的に作成される。

## membersテーブル

|Column|Type|Options|
|------|----|-------|
|user_id|integer|null: false, foreign_key: true|
|group_id|integer|null: false, foreign_key: true|

### Association
- belongs_to :group
- belongs_to :user

SequelPro

クエリにsql文を打っても文末の;を打つ必要はない。

コメント