2019年11月29日金曜日
2019年9月14日土曜日
MySQLでJOINとGROUP BYとCOUNTを組み合わせた場合
「仕事」と「申し込み」の以下のようなテーブルを結合して
▼tb_job(仕事)
|job_id|name|
|1|漁師|
|2|医者|
|3|農家|
|4|警官|
▼tb_contact(申し込み)
|contact_id|job_id|user|
|1|2|佐藤|
|2|2|田中|
|3|1|本村|
各仕事の申込数を以下のように出力したいと思っています。
▼理想
|job_id|name|申込数|
|1|漁師|1|
|2|医者|2|
|3|農家|0|
|4|警官|0|
そこで上記2つ「tb_contact」を「job_id」でGROUP BYして
SQLで以下のように結合するのですが
SELECT *,COUNT(*) FROM tb_contact RIGHT JOIN tb_job ON tb_contact.job_id = tb_job.job_id GROUP BY tb_contact.job_id;
下記のように申し込みがある仕事については集計できるのですが、
申し込みがない仕事については1括りにされてしまい、COUNTにも
その合計が表示されてしまいます。
▼結果
|contact_id|job_id|user|job_id|name|COUNT(*)
|NULL|NULL|NULL|3|農家|2
|3|1|本村|1|漁師|1
|1|2|佐藤|2|医者|2
「▼理想」のように出力するにはどの様なSQL文を投げれば良いのでしょうか。
ご教授のほど宜しくお願い致します。
↓
コレに対する回答
こちらのページをそのままメモ
▼tb_job(仕事)
|job_id|name|
|1|漁師|
|2|医者|
|3|農家|
|4|警官|
▼tb_contact(申し込み)
|contact_id|job_id|user|
|1|2|佐藤|
|2|2|田中|
|3|1|本村|
各仕事の申込数を以下のように出力したいと思っています。
▼理想
|job_id|name|申込数|
|1|漁師|1|
|2|医者|2|
|3|農家|0|
|4|警官|0|
そこで上記2つ「tb_contact」を「job_id」でGROUP BYして
SQLで以下のように結合するのですが
SELECT *,COUNT(*) FROM tb_contact RIGHT JOIN tb_job ON tb_contact.job_id = tb_job.job_id GROUP BY tb_contact.job_id;
下記のように申し込みがある仕事については集計できるのですが、
申し込みがない仕事については1括りにされてしまい、COUNTにも
その合計が表示されてしまいます。
▼結果
|contact_id|job_id|user|job_id|name|COUNT(*)
|NULL|NULL|NULL|3|農家|2
|3|1|本村|1|漁師|1
|1|2|佐藤|2|医者|2
「▼理想」のように出力するにはどの様なSQL文を投げれば良いのでしょうか。
ご教授のほど宜しくお願い致します。
↓
コレに対する回答
とりあえず、一番の原因はgroup by に 「tb_contactの」job_idを指定していることです。
tb_contactのjob_idに、3や4の値はないわけで、right joinした結果も、その値は当然nullです。
その結果「group by の値はnull」として、一列になってしまいます。
ということで、元のSQL文への変更を最小限にするなら
tb_contactのjob_idに、3や4の値はないわけで、right joinした結果も、その値は当然nullです。
その結果「group by の値はnull」として、一列になってしまいます。
ということで、元のSQL文への変更を最小限にするなら
SELECT *,COUNT(*) FROM tb_contact RIGHT JOIN tb_job ON tb_contact.job_id = tb_job.job_id GROUP BY tb_job.job_id;
となります。
補足として、
group by または集計関数 を使用する時、Selectに「group by に指定されていない集計関数以外の列」を指定できてしまうのはMYSQLの独自拡張です。
今回も最初のSQLが「通ってしまう」ことが誤解の一員になっているんじゃないかと思います。
参考:寛容なMySQLを非寛容にすること(その3) | inquisitor
それをふまえた上で「理想」と同じ出力にするなら、こんな感じで。
補足として、
group by または集計関数 を使用する時、Selectに「group by に指定されていない集計関数以外の列」を指定できてしまうのはMYSQLの独自拡張です。
今回も最初のSQLが「通ってしまう」ことが誤解の一員になっているんじゃないかと思います。
参考:寛容なMySQLを非寛容にすること(その3) | inquisitor
それをふまえた上で「理想」と同じ出力にするなら、こんな感じで。
SELECT tb_job.job_id,tb_job.name,COUNT(tb_contact.job_id) AS `申込数` FROM tb_contact RIGHT JOIN tb_job ON tb_contact.job_id = tb_job.job_id GROUP BY tb_job.job_id,tb_job.name;
ちなみに、私の場合、
- JOINするテーブルには別名をつける(同じテーブルを複数JOINすることも多々あるため)
- RIGHT JOINは使用しない(RIGHT JOINはLEFT JOINに置き換え可能で、統一したほうが可読性が良くなるため)
というのを習慣にしているので、私が書くならこんな感じになります。
SELECT A.job_id,A.name,COUNT(B.job_id) AS `申込数` FROM tbl_job AS A LEFT JOIN tbl_contact AS B ON A.job_id=B.job_id GROUP by A.job_id,A.name;
こちらのページをそのままメモ
2019年8月30日金曜日
CentOS6とApache2.2.15の環境でLet's Encryptを複数のバーチャルホスト(複数のドメイン)で設定
www.example.com と example.com の2つを設定する
すでにSSLなしでは(80)では通信できている状態
CentOS release 6.10 (Final)
Apache/2.2.15
yum -y install centos-release-scl
yum -y install python27 python27-python-tools
cd /usr/bin
wget https://dl.eff.org/certbot-auto
chmod 755 certbot-auto
# scl enable python27 bash
# python -V
Python 2.7.13
certbot-auto certonly --webroot -w /var/www/html/example.com -d www.example.com,example.com -m info@example.com
ここまでは下記サイトを参考にさせていただきました。
https://qiita.com/mindwood/items/4f09da35fa9ffff6f53d
SSL関連の設定を3つのファイルに分ける。
/etc/httpd/conf.d/ssl.conf
ssl.conf → SSLの共通設定
ssl.www.example.com.conf → https://www.example.com 用の設定
ssl.example.com.conf → https://example.com 用の設定
apacheはconf.d以下に配置された「.conf」ファイルをhttpd.confにインクルードするので追加の設定は新たにファイルをこしらえたほうがすっきりします。
まず、ssl.confをコピーします。
cp ssl.conf ssl.www.example.com.conf
ssl.confの設定
の項目をガッツリ削除。
ssl.confには、wwwとwwwなしで使う共通設定のみ残します。
NameVirtualHost *:443 を追記する(どこでもいい。迷ったら一番最後)
次は、www.example.com.confの設定。
www.example.com.confからssl.confに残した部分を削除。
以下の部分を修正
↓
「DocumentRoot」と「ServerName」の項目を有効にする。
DocumentRoot "/var/www/html/example.com" #環境に合わせて修正する
ServerName www.example.com:443 #環境に合わせて修正する
下記も修正
#SSLProtocol all -SSLv2
↓
SSLProtocol all -SSLv2 -SSLv3
#SSLCipherSuite DEFAULT:!EXP:!SSLv2:!DES:!IDEA:!SEED:+3DES
↓
SSLCipherSuite DEFAULT:!EXP:!SSLv2:!DES:!IDEA:!SEED:+3DES!RC4
#SSLCertificateFile /etc/pki/tls/certs/localhost.crt
↓
SSLCertificateFile /etc/letsencrypt/live/www.example.com/cert.pem
#SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
↓
SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem
#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
↓
SSLCertificateChainFile /etc/letsencrypt/live/www.example.com/chain.pem
設定を確認。
apachectl configtest
syntax OK と表示されたらwww.example.com.confの設定は完了。
次にexample.com.confの設定をします。
cp www.example.com.conf example.com.conf
example.com.confの設定を修正。
設定を確認。
apachectl configtest
apacheリスタートします。
両方のSSL通信を確認する。
ここまでは下記サイトを参考にさせていただきました。
http://y-stream.blogspot.com/2011/09/apachessl.html
毎週土曜日の午前3時に更新チェック
# crontab -e
00 02 * * 5 scl enable python27 "bash -c \"certbot-auto renew --post-hook '/sbin/service httpd restart'\"" > /var/log/certbot.log 2>&1
ここまでは下記サイトを参考にさせていただきました。
https://qiita.com/mindwood/items/4f09da35fa9ffff6f53d
すでにSSLなしでは(80)では通信できている状態
CentOS release 6.10 (Final)
Apache/2.2.15
yum -y install centos-release-scl
yum -y install python27 python27-python-tools
cd /usr/bin
wget https://dl.eff.org/certbot-auto
chmod 755 certbot-auto
# scl enable python27 bash
# python -V
Python 2.7.13
certbot-auto certonly --webroot -w /var/www/html/example.com -d www.example.com,example.com -m info@example.com
ここまでは下記サイトを参考にさせていただきました。
https://qiita.com/mindwood/items/4f09da35fa9ffff6f53d
SSL関連の設定を3つのファイルに分ける。
/etc/httpd/conf.d/ssl.conf
ssl.conf → SSLの共通設定
ssl.www.example.com.conf → https://www.example.com 用の設定
ssl.example.com.conf → https://example.com 用の設定
apacheはconf.d以下に配置された「.conf」ファイルをhttpd.confにインクルードするので追加の設定は新たにファイルをこしらえたほうがすっきりします。
まず、ssl.confをコピーします。
cp ssl.conf ssl.www.example.com.conf
ssl.confの設定
ssl.confには、wwwとwwwなしで使う共通設定のみ残します。
NameVirtualHost *:443 を追記する(どこでもいい。迷ったら一番最後)
次は、www.example.com.confの設定。
www.example.com.confからssl.confに残した部分を削除。
以下の部分を修正
↓
「DocumentRoot」と「ServerName」の項目を有効にする。
DocumentRoot "/var/www/html/example.com" #環境に合わせて修正する
ServerName www.example.com:443 #環境に合わせて修正する
下記も修正
#SSLProtocol all -SSLv2
↓
SSLProtocol all -SSLv2 -SSLv3
#SSLCipherSuite DEFAULT:!EXP:!SSLv2:!DES:!IDEA:!SEED:+3DES
↓
SSLCipherSuite DEFAULT:!EXP:!SSLv2:!DES:!IDEA:!SEED:+3DES!RC4
#SSLCertificateFile /etc/pki/tls/certs/localhost.crt
↓
SSLCertificateFile /etc/letsencrypt/live/www.example.com/cert.pem
#SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
↓
SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem
#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
↓
SSLCertificateChainFile /etc/letsencrypt/live/www.example.com/chain.pem
設定を確認。
apachectl configtest
syntax OK と表示されたらwww.example.com.confの設定は完了。
次にexample.com.confの設定をします。
cp www.example.com.conf example.com.conf
example.com.confの設定を修正。
設定を確認。
apachectl configtest
apacheリスタートします。
両方のSSL通信を確認する。
ここまでは下記サイトを参考にさせていただきました。
http://y-stream.blogspot.com/2011/09/apachessl.html
毎週土曜日の午前3時に更新チェック
# crontab -e
00 02 * * 5 scl enable python27 "bash -c \"certbot-auto renew --post-hook '/sbin/service httpd restart'\"" > /var/log/certbot.log 2>&1
ここまでは下記サイトを参考にさせていただきました。
https://qiita.com/mindwood/items/4f09da35fa9ffff6f53d
2019年4月1日月曜日
httpdを再起動しようとすると「Address already in use」と言われ再起動できないときの対処
lsofコマンドで古いプロセスを表示し、killすればよい。
$ sudo lsof -i | grep http
httpd 27512 apache 4u IPv6 90360 0t0 TCP *:http (LISTEN)
httpd 27520 apache 4u IPv6 90360 0t0 TCP *:http (LISTEN)
27512, 27520のidをもつプロセスが残っていることが分かる。
$ sudo kill -9 27512
$ sudo kill -9 27520
これで起動するようになる。
$ sudo /etc/init.d/httpd restart
httpd を停止中: [ OK ]
httpd を起動中:
参考ページ :https://qiita.com/ysk24ok/items/ffe8d5d1479aaf5afeaa
→TOPコマンドでも確認してみる
$ sudo lsof -i | grep http
httpd 27512 apache 4u IPv6 90360 0t0 TCP *:http (LISTEN)
httpd 27520 apache 4u IPv6 90360 0t0 TCP *:http (LISTEN)
27512, 27520のidをもつプロセスが残っていることが分かる。
$ sudo kill -9 27512
$ sudo kill -9 27520
これで起動するようになる。
$ sudo /etc/init.d/httpd restart
httpd を停止中: [ OK ]
httpd を起動中:
参考ページ :https://qiita.com/ysk24ok/items/ffe8d5d1479aaf5afeaa
→TOPコマンドでも確認してみる
2019年3月7日木曜日
2019年2月15日金曜日
2019年1月5日土曜日
phpMyAdminでCSVファイルをインポートする手順
CREATE TABLE IF NOT EXISTS `m_item` (
item_id int(11) NOT NULL auto_increment,
item_name varchar(80),
item_price int(11) NOT NULL default 0,
PRIMARY KEY (item_id)
)
以下のカンマ区切りデータ(CSV)をインポートする手順
※文字コードは予めUTF-8に変換しておくこと。
"チョコレート",100
"アイスクリーム",200
"ポテトチップス",180
"ラムネ",100
"ピーナツ",150
phpMyAdminで該当のデータベースを選択、テーブル名→インポートと進んで各パラメータを指定する。
インポートするファイルの形式 CSV
オプション
フィールド区切り記号 ,
フィールド囲み記号 "
フィールドのエスケープ記号 \
行の終端記号 auto
カラム名 item_name,item_price
参照サイト:http://memo.wokaki.com/import_csv_phpmyadmin/
↑これでいけた。
CSVは""で囲む必要あり。
インポートのオプションでカラム名も必要。
登録:
投稿 (Atom)