Yaru Gtk Themes Available in Dark and Light Variants for Ubuntu 18.04

Yaru-light and Yaru-dark based on ‘Yaru theme (Ubuntu community theme)’ https://github.com/ubuntu/yaru powered by the community on the Ubuntu hub. Yaru theme design for GTK 3, GTK 2 and Gnome-Shell. Some of the additional tweaks:

  • Switch gtk control with round radius.
  • Transparent gnome-shell.

Installation :

  1. Just unzip the file and place it in your themes directory i.e. 
    ~/.themes/
    ~/.themes/or
    /usr/share/themes/
    /usr/share/themes/
  2. Install gnome-tweak-tool
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    sudo apt install gnome-tweak-tool
    sudo apt install gnome-tweak-tool
    sudo apt install gnome-tweak-tool
  3. Select the theme as ‘Yaru-light’ or ‘Yaru-dark’

Download : https://www.gnome-look.org/p/1252100/
Base : https://github.com/ubuntu/yaru

sysctl – changing kernel parameters at runtime

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#
# /etc/sysctl.conf - Configuration file for setting system variables
# See /etc/sysctl.d/ for additional system variables.
# See sysctl.conf (5) for information.
#
#kernel.domainname = example.com
# Uncomment the following to stop low-level messages on console
#kernel.printk = 3 4 1 3
##############################################################3
# Functions previously found in netbase
#
# Uncomment the next two lines to enable Spoof protection (reverse-path filter)
# Turn on Source Address Verification in all interfaces to
# prevent some spoofing attacks
#net.ipv4.conf.default.rp_filter=1
#net.ipv4.conf.all.rp_filter=1
# Uncomment the next line to enable TCP/IP SYN cookies
# See http://lwn.net/Articles/277146/
# Note: This may impact IPv6 TCP sessions too
#net.ipv4.tcp_syncookies=1
# Uncomment the next line to enable packet forwarding for IPv4
#net.ipv4.ip_forward=1
# Uncomment the next line to enable packet forwarding for IPv6
# Enabling this option disables Stateless Address Autoconfiguration
# based on Router Advertisements for this host
#net.ipv6.conf.all.forwarding=1
###################################################################
# Additional settings - these settings can improve the network
# security of the host and prevent against some network attacks
# including spoofing attacks and man in the middle attacks through
# redirection. Some network environments, however, require that these
# settings are disabled so review and enable them as needed.
#
# Do not accept ICMP redirects (prevent MITM attacks)
#net.ipv4.conf.all.accept_redirects = 0
#net.ipv6.conf.all.accept_redirects = 0
# _or_
# Accept ICMP redirects only for gateways listed in our default
# gateway list (enabled by default)
# net.ipv4.conf.all.secure_redirects = 1
#
# Do not send ICMP redirects (we are not a router)
#net.ipv4.conf.all.send_redirects = 0
#
# Do not accept IP source route packets (we are not a router)
#net.ipv4.conf.all.accept_source_route = 0
#net.ipv6.conf.all.accept_source_route = 0
#
# Log Martian Packets
#net.ipv4.conf.all.log_martians = 1
#
###################################################################
# Magic system request Key
# 0=disable, 1=enable all
# Debian kernels have this set to 0 (disable the key)
# See https://www.kernel.org/doc/Documentation/sysrq.txt
# for what other values do
#kernel.sysrq=1
###################################################################
# Protected links
#
# Protects against creating or following links under certain conditions
# Debian kernels have both set to 1 (restricted)
# See https://www.kernel.org/doc/Documentation/sysctl/fs.txt
#fs.protected_hardlinks=0
#fs.protected_symlinks=0
###################################################################
# Improving performance
# Virtual memory
# Consensus is that setting vm.dirty_ratio to 10% of RAM is a sane value if RAM is say 1 GB (so 10% is 100 MB). But if the machine has much more RAM, say 16 GB (10% is 1.6 # GB), the percentage may be out of proportion as it becomes several seconds of writeback on spinning disks. A more sane value in this case may be 3 (3% of 16 GB is #approximately 491 MB).
vm.swappiness=10
vm.dirty_ratio=10
vm.dirty_background_ratio=5
vm.vfs_cache_pressure=50
vm.dirty_background_bytes=4194304
vm.dirty_bytes=4194304
# Networking
# Increasing the size of the receive queue.
net.core.netdev_max_backlog=100000
net.core.netdev_budget=50000
net.core.netdev_budget_usecs=5000
#
# Increase the maximum connections default 128
net.core.somaxconn=1024
#
# Increase the memory dedicated to the network interfaces
net.core.rmem_default=1048576
net.core.rmem_max=16777216
net.core.wmem_default=1048576
net.core.wmem_max=16777216
net.core.optmem_max=65536
net.ipv4.tcp_rmem=4096 1048576 2097152
net.ipv4.tcp_wmem=4096 65536 16777216
#
# increase the default 4096 UDP limits
net.ipv4.udp_rmem_min=8192
net.ipv4.udp_wmem_min=8192
#
# Enable TCP Fast Open
net.ipv4.tcp_fastopen=3
#
# Tweak the pending connection handling
net.ipv4.tcp_max_syn_backlog=30000
net.ipv4.tcp_max_tw_buckets=2000000
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_fin_timeout=10
net.ipv4.tcp_slow_start_after_idle=0
#
# Change TCP keepalive parameters
net.ipv4.tcp_keepalive_time=60
net.ipv4.tcp_keepalive_intvl=10
net.ipv4.tcp_keepalive_probes=6
#
# Enable MTU probing
net.ipv4.tcp_mtu_probing=1
#
# TCP Timestamps
net.ipv4.tcp_timestamps=0
#
# TCP/IP stack hardening
# TCP SYN cookie protection
net.ipv4.tcp_syncookies=1
#
# TCP rfc1337
net.ipv4.tcp_rfc1337=1
#
# Reverse path filtering
net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.all.rp_filter=1
#
# Log martian packets
net.ipv4.conf.default.log_martians=1
net.ipv4.conf.all.log_martians=1
#
# Disable ICMP redirecting
net.ipv4.conf.all.accept_redirects=0
net.ipv4.conf.default.accept_redirects=0
net.ipv4.conf.all.secure_redirects=0
net.ipv4.conf.default.secure_redirects=0
net.ipv6.conf.all.accept_redirects=0
net.ipv6.conf.default.accept_redirects=0
#
# disable ICMP redirect sending when on a non router
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.default.send_redirects=0
#
# Enable Ignoring to ICMP Request
net.ipv4.icmp_echo_ignore_all=1
# # /etc/sysctl.conf - Configuration file for setting system variables # See /etc/sysctl.d/ for additional system variables. # See sysctl.conf (5) for information. # #kernel.domainname = example.com # Uncomment the following to stop low-level messages on console #kernel.printk = 3 4 1 3 ##############################################################3 # Functions previously found in netbase # # Uncomment the next two lines to enable Spoof protection (reverse-path filter) # Turn on Source Address Verification in all interfaces to # prevent some spoofing attacks #net.ipv4.conf.default.rp_filter=1 #net.ipv4.conf.all.rp_filter=1 # Uncomment the next line to enable TCP/IP SYN cookies # See http://lwn.net/Articles/277146/ # Note: This may impact IPv6 TCP sessions too #net.ipv4.tcp_syncookies=1 # Uncomment the next line to enable packet forwarding for IPv4 #net.ipv4.ip_forward=1 # Uncomment the next line to enable packet forwarding for IPv6 # Enabling this option disables Stateless Address Autoconfiguration # based on Router Advertisements for this host #net.ipv6.conf.all.forwarding=1 ################################################################### # Additional settings - these settings can improve the network # security of the host and prevent against some network attacks # including spoofing attacks and man in the middle attacks through # redirection. Some network environments, however, require that these # settings are disabled so review and enable them as needed. # # Do not accept ICMP redirects (prevent MITM attacks) #net.ipv4.conf.all.accept_redirects = 0 #net.ipv6.conf.all.accept_redirects = 0 # _or_ # Accept ICMP redirects only for gateways listed in our default # gateway list (enabled by default) # net.ipv4.conf.all.secure_redirects = 1 # # Do not send ICMP redirects (we are not a router) #net.ipv4.conf.all.send_redirects = 0 # # Do not accept IP source route packets (we are not a router) #net.ipv4.conf.all.accept_source_route = 0 #net.ipv6.conf.all.accept_source_route = 0 # # Log Martian Packets #net.ipv4.conf.all.log_martians = 1 # ################################################################### # Magic system request Key # 0=disable, 1=enable all # Debian kernels have this set to 0 (disable the key) # See https://www.kernel.org/doc/Documentation/sysrq.txt # for what other values do #kernel.sysrq=1 ################################################################### # Protected links # # Protects against creating or following links under certain conditions # Debian kernels have both set to 1 (restricted) # See https://www.kernel.org/doc/Documentation/sysctl/fs.txt #fs.protected_hardlinks=0 #fs.protected_symlinks=0 ################################################################### # Improving performance # Virtual memory # Consensus is that setting vm.dirty_ratio to 10% of RAM is a sane value if RAM is say 1 GB (so 10% is 100 MB). But if the machine has much more RAM, say 16 GB (10% is 1.6 # GB), the percentage may be out of proportion as it becomes several seconds of writeback on spinning disks. A more sane value in this case may be 3 (3% of 16 GB is #approximately 491 MB). vm.swappiness=10 vm.dirty_ratio=10 vm.dirty_background_ratio=5 vm.vfs_cache_pressure=50 vm.dirty_background_bytes=4194304 vm.dirty_bytes=4194304 # Networking # Increasing the size of the receive queue. net.core.netdev_max_backlog=100000 net.core.netdev_budget=50000 net.core.netdev_budget_usecs=5000 # # Increase the maximum connections default 128 net.core.somaxconn=1024 # # Increase the memory dedicated to the network interfaces net.core.rmem_default=1048576 net.core.rmem_max=16777216 net.core.wmem_default=1048576 net.core.wmem_max=16777216 net.core.optmem_max=65536 net.ipv4.tcp_rmem=4096 1048576 2097152 net.ipv4.tcp_wmem=4096 65536 16777216 # # increase the default 4096 UDP limits net.ipv4.udp_rmem_min=8192 net.ipv4.udp_wmem_min=8192 # # Enable TCP Fast Open net.ipv4.tcp_fastopen=3 # # Tweak the pending connection handling net.ipv4.tcp_max_syn_backlog=30000 net.ipv4.tcp_max_tw_buckets=2000000 net.ipv4.tcp_tw_reuse=1 net.ipv4.tcp_fin_timeout=10 net.ipv4.tcp_slow_start_after_idle=0 # # Change TCP keepalive parameters net.ipv4.tcp_keepalive_time=60 net.ipv4.tcp_keepalive_intvl=10 net.ipv4.tcp_keepalive_probes=6 # # Enable MTU probing net.ipv4.tcp_mtu_probing=1 # # TCP Timestamps net.ipv4.tcp_timestamps=0 # # TCP/IP stack hardening # TCP SYN cookie protection net.ipv4.tcp_syncookies=1 # # TCP rfc1337 net.ipv4.tcp_rfc1337=1 # # Reverse path filtering net.ipv4.conf.default.rp_filter=1 net.ipv4.conf.all.rp_filter=1 # # Log martian packets net.ipv4.conf.default.log_martians=1 net.ipv4.conf.all.log_martians=1 # # Disable ICMP redirecting net.ipv4.conf.all.accept_redirects=0 net.ipv4.conf.default.accept_redirects=0 net.ipv4.conf.all.secure_redirects=0 net.ipv4.conf.default.secure_redirects=0 net.ipv6.conf.all.accept_redirects=0 net.ipv6.conf.default.accept_redirects=0 # # disable ICMP redirect sending when on a non router net.ipv4.conf.all.send_redirects=0 net.ipv4.conf.default.send_redirects=0 # # Enable Ignoring to ICMP Request net.ipv4.icmp_echo_ignore_all=1
#
# /etc/sysctl.conf - Configuration file for setting system variables
# See /etc/sysctl.d/ for additional system variables.
# See sysctl.conf (5) for information.
#

#kernel.domainname = example.com

# Uncomment the following to stop low-level messages on console
#kernel.printk = 3 4 1 3

##############################################################3
# Functions previously found in netbase
#

# Uncomment the next two lines to enable Spoof protection (reverse-path filter)
# Turn on Source Address Verification in all interfaces to
# prevent some spoofing attacks
#net.ipv4.conf.default.rp_filter=1
#net.ipv4.conf.all.rp_filter=1

# Uncomment the next line to enable TCP/IP SYN cookies
# See http://lwn.net/Articles/277146/
# Note: This may impact IPv6 TCP sessions too
#net.ipv4.tcp_syncookies=1

# Uncomment the next line to enable packet forwarding for IPv4
#net.ipv4.ip_forward=1

# Uncomment the next line to enable packet forwarding for IPv6
#  Enabling this option disables Stateless Address Autoconfiguration
#  based on Router Advertisements for this host
#net.ipv6.conf.all.forwarding=1


###################################################################
# Additional settings - these settings can improve the network
# security of the host and prevent against some network attacks
# including spoofing attacks and man in the middle attacks through
# redirection. Some network environments, however, require that these
# settings are disabled so review and enable them as needed.
#
# Do not accept ICMP redirects (prevent MITM attacks)
#net.ipv4.conf.all.accept_redirects = 0
#net.ipv6.conf.all.accept_redirects = 0
# _or_
# Accept ICMP redirects only for gateways listed in our default
# gateway list (enabled by default)
# net.ipv4.conf.all.secure_redirects = 1
#
# Do not send ICMP redirects (we are not a router)
#net.ipv4.conf.all.send_redirects = 0
#
# Do not accept IP source route packets (we are not a router)
#net.ipv4.conf.all.accept_source_route = 0
#net.ipv6.conf.all.accept_source_route = 0
#
# Log Martian Packets
#net.ipv4.conf.all.log_martians = 1
#

###################################################################
# Magic system request Key
# 0=disable, 1=enable all
# Debian kernels have this set to 0 (disable the key)
# See https://www.kernel.org/doc/Documentation/sysrq.txt
# for what other values do
#kernel.sysrq=1

###################################################################
# Protected links
#
# Protects against creating or following links under certain conditions
# Debian kernels have both set to 1 (restricted) 
# See https://www.kernel.org/doc/Documentation/sysctl/fs.txt
#fs.protected_hardlinks=0
#fs.protected_symlinks=0

###################################################################
# Improving performance
# Virtual memory
# Consensus is that setting vm.dirty_ratio to 10% of RAM is a sane value if RAM is say 1 GB (so 10% is 100 MB). But if the machine has much more RAM, say 16 GB (10% is 1.6 # GB), the percentage may be out of proportion as it becomes several seconds of writeback on spinning disks. A more sane value in this case may be 3 (3% of 16 GB is #approximately 491 MB).

vm.swappiness=10
vm.dirty_ratio=10
vm.dirty_background_ratio=5
vm.vfs_cache_pressure=50
vm.dirty_background_bytes=4194304
vm.dirty_bytes=4194304

# Networking
# Increasing the size of the receive queue.
net.core.netdev_max_backlog=100000
net.core.netdev_budget=50000
net.core.netdev_budget_usecs=5000
#
# Increase the maximum connections default 128
net.core.somaxconn=1024
#
# Increase the memory dedicated to the network interfaces
net.core.rmem_default=1048576
net.core.rmem_max=16777216
net.core.wmem_default=1048576
net.core.wmem_max=16777216
net.core.optmem_max=65536
net.ipv4.tcp_rmem=4096 1048576 2097152
net.ipv4.tcp_wmem=4096 65536 16777216
#
# increase the default 4096 UDP limits
net.ipv4.udp_rmem_min=8192
net.ipv4.udp_wmem_min=8192
#
# Enable TCP Fast Open
net.ipv4.tcp_fastopen=3
#
# Tweak the pending connection handling
net.ipv4.tcp_max_syn_backlog=30000
net.ipv4.tcp_max_tw_buckets=2000000
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_fin_timeout=10
net.ipv4.tcp_slow_start_after_idle=0
#
# Change TCP keepalive parameters
net.ipv4.tcp_keepalive_time=60
net.ipv4.tcp_keepalive_intvl=10
net.ipv4.tcp_keepalive_probes=6
#
# Enable MTU probing
net.ipv4.tcp_mtu_probing=1
#
# TCP Timestamps
net.ipv4.tcp_timestamps=0
#
# TCP/IP stack hardening
# TCP SYN cookie protection
net.ipv4.tcp_syncookies=1
#
# TCP rfc1337
net.ipv4.tcp_rfc1337=1
#
# Reverse path filtering
net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.all.rp_filter=1
#
# Log martian packets
net.ipv4.conf.default.log_martians=1
net.ipv4.conf.all.log_martians=1
#
# Disable ICMP redirecting
net.ipv4.conf.all.accept_redirects=0
net.ipv4.conf.default.accept_redirects=0
net.ipv4.conf.all.secure_redirects=0
net.ipv4.conf.default.secure_redirects=0
net.ipv6.conf.all.accept_redirects=0
net.ipv6.conf.default.accept_redirects=0
#
# disable ICMP redirect sending when on a non router
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.default.send_redirects=0
#
# Enable Ignoring to ICMP Request
net.ipv4.icmp_echo_ignore_all=1

 
Source : https://wiki.archlinux.org/index.php/Sysctl

transfer.sh – Easy file sharing from the command line

transfer.sh เป็นบริการ file sharing แบบต้องใช้ command line ตอนนี้ก็รองรับทั้งการฝากไฟล์ที่อยู่ในเครื่อง (local file) s3 (Amazon S3) และ gdrive (Google Drive) โดยฟีเจอร์หลัก ๆ ก็มี

  • ผ่าน shell command ได้ (Powershell ด้วย)
  • ขนาดไฟล์สูงสุดได้ 10 GB
  • ฝากไฟล์ได้ 14 วัน
  • เข้ารหัสไฟล์ได้
  • กำหนดเงื่อนไข (จำนวน) การดาวน์โหลด
  • ฟรี ???

ตัวอย่างแบบเบสิคเลย

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Uploading is easy using curl
$ curl --upload-file ./hello.txt https://transfer.sh/hello.txt
https://transfer.sh/66nb8/hello.txt
$ curl -H "Max-Downloads: 1" -H "Max-Days: 5" --upload-file ./hello.txt https://transfer.sh/hello.txt
https://transfer.sh/66nb8/hello.txt
# Download the file
$ curl https://transfer.sh/66nb8/hello.txt -o hello.txt
# Uploading is easy using curl $ curl --upload-file ./hello.txt https://transfer.sh/hello.txt https://transfer.sh/66nb8/hello.txt $ curl -H "Max-Downloads: 1" -H "Max-Days: 5" --upload-file ./hello.txt https://transfer.sh/hello.txt https://transfer.sh/66nb8/hello.txt # Download the file $ curl https://transfer.sh/66nb8/hello.txt -o hello.txt
# Uploading is easy using curl
$ curl --upload-file ./hello.txt https://transfer.sh/hello.txt
https://transfer.sh/66nb8/hello.txt

$ curl -H "Max-Downloads: 1" -H "Max-Days: 5" --upload-file ./hello.txt https://transfer.sh/hello.txt
https://transfer.sh/66nb8/hello.txt
# Download the file
$ curl https://transfer.sh/66nb8/hello.txt -o hello.txt

หรือจะเป็นการ Backup MySQL ก็ทำได้เหมือนกัน

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Backup, encrypt and transfer
$ mysqldump --all-databases|gzip|gpg -ac -o-|curl -X PUT --upload-file "-" https://transfer.sh/test.txt
# Backup, encrypt and transfer $ mysqldump --all-databases|gzip|gpg -ac -o-|curl -X PUT --upload-file "-" https://transfer.sh/test.txt
# Backup, encrypt and transfer
$ mysqldump --all-databases|gzip|gpg -ac -o-|curl -X PUT --upload-file "-" https://transfer.sh/test.txt

* ถ้าใครสนใจลองเข้าไปใช้งานได้ที่เว็บ transfer.sh ส่วนตัวแล้วเป็นบริการที่ชอบเลย ด้วยความที่เป็นอะไรที่ใช้งานง่ายและมีประโยชน์จริง ๆ

** โปรเจคอยู่บน github (https://github.com/dutchcoders/transfer.sh) จะเอามาทำใช้เองก็ได้มี Docker ให้ด้วย

สร้าง docker container สำหรับทำ REST API กัน – Full fake data

ในวันที่ต้อง Mock API แบบด่วน ๆ สำหรับทดสอบ Front-end (แต่ Back-end จริง ๆ มันยังอยู่แค่ในร่างออกแบบ) งั้นก็เริ่มกันเลย

เราใช้ json-server เป็นตัวช่วยทำ Mock API ซึ่งก็ตอบโจทย์และเร็วสุดละ สิ่งที่เราต้องทำเพิ่มคือสร้างชุดข้อมูลสำหรับทดสอบเท่านั้นเอง

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npm install -g json-server
npm install -g json-server
npm install -g json-server

ส่วนการสร้างชุดข้อมูลก็ใช้ faker.js (เราใช้ lodash เพิ่ม ก็ติดตั้งเข้าไปพร้อมกันเลย)

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npm install faker lodash
npm install faker lodash
npm install faker lodash

สร้างชุดข้อมูลแบบ random ด้วยไฟล์ชื่อ generator.js เข้าไป

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// generator.js
module.exports = function () {
var faker = require("faker");
var _ = require("lodash");
return {
customers: _.times(Math.floor((Math.random() * 1000) + 1), function (n) {
return {
id: n+1,
firstname: faker.name.firstName(),
lastname: faker.name.lastName(),
birthdate: faker.date.past(50, new Date("Sat Sep 20 1992 21:35:02 GMT+0700 (ICT)")),
address: faker.address.streetAddress(),
city: faker.address.city(),
country: faker.address.country(),
email: faker.internet.email(),
avatar: faker.internet.avatar()
}
})
}
}
// generator.js module.exports = function () { var faker = require("faker"); var _ = require("lodash"); return { customers: _.times(Math.floor((Math.random() * 1000) + 1), function (n) { return { id: n+1, firstname: faker.name.firstName(), lastname: faker.name.lastName(), birthdate: faker.date.past(50, new Date("Sat Sep 20 1992 21:35:02 GMT+0700 (ICT)")), address: faker.address.streetAddress(), city: faker.address.city(), country: faker.address.country(), email: faker.internet.email(), avatar: faker.internet.avatar() } }) } }
// generator.js
module.exports = function () {
    var faker = require("faker");
    var _ = require("lodash");
    return {
        customers: _.times(Math.floor((Math.random() * 1000) + 1), function (n) {
            return {
                id: n+1,
                firstname: faker.name.firstName(),
                lastname: faker.name.lastName(),
                birthdate: faker.date.past(50, new Date("Sat Sep 20 1992 21:35:02 GMT+0700 (ICT)")),
                address: faker.address.streetAddress(),
                city: faker.address.city(),
                country: faker.address.country(),
                email: faker.internet.email(),
                avatar: faker.internet.avatar()
            }
        })
    }
}

หลังจากที่เรา Start Server ด้วยคำสั่ง 

json-server generator.js
json-server generator.js ข้อมูลที่เรา generate ขึ้นหน้าตาก็ประมาณนี้

ท้ายสุดเราก็แพ็คลง Container เลย โดยสร้าง Dockerfile ไว้ใช้งานยาว ๆ  (เป็นลางว่า Back-end จะยังไม่เสร็จในเร็ววันใช่ไหม 55555)

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
FROM node:10-alpine
LABEL author="mf"
LABEL version="latest"
ENV NPM_CONFIG_LOGLEVEL info
ENV TZ Asia/Bangkok
RUN apk add --no-cache tzdata \
&& cp /usr/share/zoneinfo/Asia/Bangkok /etc/localtime \
&& echo "Asia/Bangkok" > /etc/timezone \
&& rm -rf /var/cache/apk/*
# Create application directory
RUN mkdir -p /data \
&& npm install -g json-server lodash faker
WORKDIR /data
VOLUME [ "/data" ]
EXPOSE 3000
# Default command
ENTRYPOINT ["json-server"]
CMD ["--help"]
FROM node:10-alpine LABEL author="mf" LABEL version="latest" ENV NPM_CONFIG_LOGLEVEL info ENV TZ Asia/Bangkok RUN apk add --no-cache tzdata \ && cp /usr/share/zoneinfo/Asia/Bangkok /etc/localtime \ && echo "Asia/Bangkok" > /etc/timezone \ && rm -rf /var/cache/apk/* # Create application directory RUN mkdir -p /data \ && npm install -g json-server lodash faker WORKDIR /data VOLUME [ "/data" ] EXPOSE 3000 # Default command ENTRYPOINT ["json-server"] CMD ["--help"]
FROM node:10-alpine

LABEL author="mf"
LABEL version="latest"

ENV NPM_CONFIG_LOGLEVEL info
ENV TZ Asia/Bangkok

RUN apk add --no-cache tzdata \
    && cp /usr/share/zoneinfo/Asia/Bangkok /etc/localtime \
    && echo "Asia/Bangkok" >  /etc/timezone \
    && rm -rf /var/cache/apk/*

# Create application directory
RUN mkdir -p /data \
    && npm install -g json-server lodash faker
WORKDIR /data

VOLUME [ "/data" ]
EXPOSE 3000

# Default command
ENTRYPOINT ["json-server"]
CMD ["--help"]

หลังจาก build Dockerfile แล้วก็ลองรันกันเลย ถ้าไม่ทำอะไรผิดพลาดผลลัพธ์มันก็ควรจะเป็นดังรูป

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
docker run -d -p 3000:3000 -v `pwd`/app:/data mf/mockup-api --watch generator.js --host 0.0.0.0
docker run -d -p 3000:3000 -v `pwd`/app:/data mf/mockup-api --watch generator.js --host 0.0.0.0
docker run -d -p 3000:3000 -v `pwd`/app:/data mf/mockup-api --watch generator.js --host 0.0.0.0

จบปิ๊งง ^_^

#ยังคิดถึงเสมอ

กะละมังอาบน้ำของมังกี้ยังวางอยู่หน้าบ้านเหมือนเดิม
สายจูง ลูกบอลอีกลูกก็ยังอยู่ในลังของเล่นอยู่
บางครั้งก็มีขนเธอปลิวมาบ้าง ถึงแม้เราจะทำความสะอาดบ้านครั้งใหญ่ไปหลายรอบละ
ต้นมะลิที่ปลูกไว้หลังบ้าน ตรงที่เธอนอนอยู่… ต้นที่เป็นของเธอก็ยังรอดปลอดภัย
ผ่านมาปีนึงละ ก็ยังคิดถึงเธอเสมอ

 

 

Hierarchical and recursive queries in MySQL

Hierarchical query คืออะไร ?

A hierarchical query is a type of SQL query that handles hierarchical model data. They are special cases of more general recursive fixpoint queries, which compute transitive closures.

อยากบอก(บ่น) ว่าก่อนที่ MySQL 8 จะออกนี่การดึงข้อมูลแบบลำดับชั้นลักษณะต้นไม้ (Tree) แบบนี้โคตรเปลืองพลังงาน แต่ตอนนี้ดีขึ้นมาก ต้องขอบคุณจริง ๆ ที่ MySQL อิมพลีเมนต์ Common Table Expression (CTE) ให้ใช้ได้ซะที เขียนคำสั่งสั้นลง ประสิทธิภาพดีขึ้น (ก็แหงสิเจ้าของเค้าทำออกมาเอง)

ยกตัวอย่างข้อมูลลักษณะแบบลำดับชั้น เช่น โครงสร้างองค์กร เธรดในคอมเมนต์ต่าง ๆ ข้อมูล Categories and sub-categories ที่เห็นภาพชัด ๆ  เลยคือ โครงสร้างองค์กร (Organization charts ) นี่ง่ายสุดละ มีหัวหน้าเป็นรูทและมีลูกน้องในความดูแลและบางทีลูกน้องก็มีเบ้ต่อลงไปอีกที ลักษณะข้อมูลแบบรูปนี้เลย


ว่าแล้วก็ติดตั้ง MySQL 8 สำหรับใช้งานกัน

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
docker run -d -p 3306:3306 --name mysqltest --restart always -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=demo mysql:8
docker run -d -p 3306:3306 --name mysqltest --restart always -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=demo mysql:8
docker run -d -p 3306:3306 --name mysqltest --restart always -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=demo mysql:8

โดยธรรมเนียมปฏิบัติทั่วไป ของตารางที่เก็บข้อมูลในลักษณะนี้ก็จะออกแบบคล้าย ๆ แบบนี้ โดยให้คอลัมภ์ parent เก็บข้อมูลหัวหน้า

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
DROP TABLE IF EXISTS category;
CREATE TABLE IF NOT EXISTS category(
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
parent INT DEFAULT NULL
);
INSERT INTO category VALUES
(1,'Root A', NULL),
(2,'Item 1', 1),
(3,'Item 2', 1),
(4,'Item 3', 3),
(5,'Root B', NULL),
(6,'Item 4', 5),
(7,'Item 5', 6),
(8,'Root C', NULL),
(9,'Item 6', 8);
DROP TABLE IF EXISTS category; CREATE TABLE IF NOT EXISTS category( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20) NOT NULL, parent INT DEFAULT NULL ); INSERT INTO category VALUES (1,'Root A', NULL), (2,'Item 1', 1), (3,'Item 2', 1), (4,'Item 3', 3), (5,'Root B', NULL), (6,'Item 4', 5), (7,'Item 5', 6), (8,'Root C', NULL), (9,'Item 6', 8);
DROP TABLE IF EXISTS category;
CREATE TABLE IF NOT EXISTS category(
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(20) NOT NULL,
        parent INT DEFAULT NULL
);

INSERT INTO category VALUES
(1,'Root A', NULL),
(2,'Item 1', 1),
(3,'Item 2', 1),
(4,'Item 3', 3),
(5,'Root B', NULL),
(6,'Item 4', 5),
(7,'Item 5', 6),
(8,'Root C', NULL),
(9,'Item 6', 8);

การดึงข้อมูลในลักษณะ Recursive MySQL ได้เตรียมคำสั่งให้แล้ว รูปแบบการใช้งาน

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
with_clause:
WITH [RECURSIVE]
cte_name [(col_name [, col_name] ...)] AS (subquery)
[, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...
with_clause: WITH [RECURSIVE] cte_name [(col_name [, col_name] ...)] AS (subquery) [, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...
with_clause:
    WITH [RECURSIVE]
        cte_name [(col_name [, col_name] ...)] AS (subquery)
        [, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...

ลักษณะของคำสั่งนี้คือ


*ภาพจาก mysqltutorial : A Definitive Guide To MySQL Recursive CTE

เรามาดูผลลัพธ์กัน

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
WITH RECURSIVE categorypath(id, name, dept, breadcrumbs) AS
(
SELECT id, name, 0, CAST(name AS CHAR(1000))
FROM category
WHERE parent IS NULL
UNION ALL
SELECT c.id, c.name, cp.dept + 1, CONCAT_WS('/', cp.breadcrumbs, c.name)
FROM categorypath cp
JOIN category c ON cp.id = c.parent
)
SELECT * FROM categorypath ORDER BY breadcrumbs;
WITH RECURSIVE categorypath(id, name, dept, breadcrumbs) AS ( SELECT id, name, 0, CAST(name AS CHAR(1000)) FROM category WHERE parent IS NULL UNION ALL SELECT c.id, c.name, cp.dept + 1, CONCAT_WS('/', cp.breadcrumbs, c.name) FROM categorypath cp JOIN category c ON cp.id = c.parent ) SELECT * FROM categorypath ORDER BY breadcrumbs;
WITH RECURSIVE categorypath(id, name, dept, breadcrumbs) AS
(
  SELECT id, name, 0, CAST(name AS CHAR(1000))
  FROM category 
  WHERE parent IS NULL
  UNION ALL
  SELECT c.id, c.name, cp.dept + 1, CONCAT_WS('/', cp.breadcrumbs, c.name) 
  FROM categorypath cp 
    JOIN category c ON cp.id = c.parent
)
SELECT * FROM categorypath ORDER BY breadcrumbs;

ไปอ่านเพิ่มเติมกันได้ที่

  • https://mysqlserverteam.com/mysql-8-0-labs-recursive-common-table-expressions-in-mysql-ctes/
  • https://www.percona.com/live/17/sites/default/files/slides/Recursive%20Query%20Throwdown.pdf
  • https://en.wikipedia.org/wiki/Hierarchical_and_recursive_queries_in_SQL

จบปิ๊ง ^__^
ป.ล.1 วันหยุด วันฝนตกฉันควรนอนกกใครสักคนอยู่ใต้ผ้าห่มนี่นา
ป.ล.2 เศร้าาาวันทำงาน

มินิรีวิว Mi Notebook Pro กับหนึ่งเดือนที่ผ่านมา

เมื่อช่วงเดือนพฤศจิกายนปีที่แล้ว (2017) Xiaomi ได้จัดงาน Mi Product Launch และเปิดตัว Mi Notebook Pro แล็บท็อปสุดบางสเปคระดับบน ซึ่งเป็นรุ่นต่อจาก Mi Notebook Air โดยเปิดตัวรุ่นย่อยออกมาแยกตามซีพียูและความจุ ดังนี้

  • Core i5 + RAM 8GB ราคา 5599 หยวน (28,xxx บาท)
  • Core i7 + RAM 8GB ราคา 6399 หยวน (32,xxx บาท)
  • Core i7 + RAM 16GB ราคา 6999 หยวน (35,xxx บาท)

เราเองเพิ่งได้เครื่องตัว Core i7 RAM 16 GB มาเดือนที่แล้ว สนนราคาที่ขายในไทยก็อยู่ที่ 37,900 บาท (ก็ยังถือเป็นเครื่องหิ้วอยู่ ศูนย์ Xiaomi ในไทยยังไม่มีวี่แววว่าจะนำเข้ามาจำหน่าย)

ดีไซน์และตัวเครื่อง

ดีไซน์โดยรวมของตัวเครื่องบอกตรง ๆ ว่าเอามาชนกับ Macbook Pro ของ Apple แน่นอนอย่างไม่ต้องสงสัย โดยดีไซน์ภายนอกของ Mi Notebook Pro สีเทาเข้ม(Dark Gray) บอดี้ทำจากแม็กนีเซียมอัลลอย หนัก 1.95 กก. หน้าจอขนาด 15.6 นิ้ว Full-HD (1920×1080) 16:9 IPS Display 141 PPI ขอบจอบาง ครอบทับด้วย Gorilla Glass 3 ซีพียูเป็น Intel Core i7-8550U Gen 8 มี 4 แกน 8 เธรด ความถี่ 4.0 GHz (1800 – 4000 MHz) การ์ดจอ NVIDIA GeForce MX150 สำหรับอัลตร้าบุ๊ค แรม DRR4 400 MHz Dual-channel (10-10-10-28 CR1) ขนาด 16 GB SSD PCIe NVMe ขนาด 256 GB (Samsung PM961 MZVLW256HEHP)
คีย์บอร์ดขนาดฟูลไซส์ มีไฟ backlit สำหรับใช้งานในที่มืดและบริเวณ Touchpad มีเซนเซอร์สแกนลายนิ้วมือมาให้ด้วย ใช้ในการล็อกอินผ่าน Windows จากการใช้งานถือว่าทำงานได้เร็วและแม่นยำมาก ส่วนพอร์ทสำหรับเชื่อมต่อมี

  • USB Type C จำนวน 2 พอร์ท โดยแยกเป็น 1 พอร์ทที่รองรับเฉพาะถ่ายโอนข้อมูล อีกพอร์ทเป็น Full Functional ทั้งชาร์จไฟและถ่ายโอนข้อมูล
  • Full HDMI
  • USB 3.0 จำนวน 2 พอร์ท
  • พอร์ท 3-in-1 SD Card
  • ช่องหูฟัง 3.5 มม.

ส่วนสเปคอุปกรณ์อื่นก็มี

  • ลำโพง Harman Infinity มาพร้อมระบบเสียง Dolby Atmos
  • SSD 256GB PCIe (พร้อมช่อง NVMe อีก 4 ช่องสำหรับเพิ่มหน่วยความจำ)
  • Wi-Fi AC Dual-Band ที่ 2.4GHz, 5GHz Dual-band
  • Bluetooth 4.1

การใช้งานและแบตเตอรี่

จากการใช้งานมาได้สักระยะ ปัญหาที่พบคือปัญหาเรื่องพอร์ทเชื่อมต่อ ที่จริงก็ไม่ใช่ปัญหาของ Mi Notebook Pro หรอก โดยลักษณะใช้งานของตัวเองที่ใช้งานพอร์ทอีเธอร์เนตเป็นหลักรวมทั้งพอร์ท VGA ซึ่งก็หลีกหนีไม่พ้นต้องหาอุปกรณ์เพิ่ม ส่วนการใช้งานอื่นที่เครื่องมีมาให้สามารถรองรับได้ในระดับที่น่าพอใจ

ส่วนแบตเตอรี่ (สเปคเป็น 8000mAh lithium-polymer battery) จากการใช้งานเฉลี่ยก็ราว ๆ 8 ชั่วโมงทั้งนี้ทั้งนั้นก็ขึ้นกับลักษณะการใช้งานด้วย ระยะเวลาชาร์ทอยู่ที่ 1 ชั่วโมงกว่า รองรับ Quick charge ราว ๆ 35-40 นาทีก็ 50% อันนี้เราว่าผ่านกรณีสำหรับการเป็นอัลตร้าบุ๊ค

สรุป

Mi Notebook Pro นับเป็นอัลตราบุ๊คที่ประสิทธิภาพต่อราคาถือว่าคุ้มค่า ด้วยการออกแบบและวัสดุเองที่เน้นความสวยงามและมินิมอลิลต์ตามเทรนด์นิยม การแสดงผลของหน้าจอ IPSขนาด 15.6 นิ้วก็ทำได้ดี การใช้งานกรณีอยู่กลางแจ้งก็ไม่ได้แย่อะไร รวมทั้งน้ำหนักที่สะดวกต่อการพกพา

ข้อดี

  • ตัวเครื่องและวัสดุให้ความรู้สึกพรีเมี่ยม (*เพิ่มเติม* ถึงแม้วัสดุจะเป็นแม็กนีเซียมอัลลอย แต่ความรู้สึกเวลาสัมผัสความเนี๊ยบก็ยังเทียบกับ Macbook Pro ไม่ได้)
  • ประสิทธิภาพดี (i7-8550U รวมกับ RAM 16 GB นี่สบาย)
  • เสียงจากลำโพงดีเลย
  • Touchpad ตอบสนองได้ดี
  • แสกนลายนิ้วมือทำงานได้เร็วและแม่นยำ
  • คุ้มค่า คุ้มราคา

ข้อเสีย

  • การระบายความร้อนยังทำได้ไม่ดี (*เพิ่มเติม* ช่วงซีพียูความเร็ว < 2 GHz แทบไม่ได้ยินเสียงพัดลม กรณีเร่งสปีดซีพียูช่วงแตะ 4 GHz พัดลมเริ่มกระหึ่มทันที)
  • Windows 10 เป็นเวอร์ชั่นภาษาจีน
  • แป้นคีย์บอร์ดไม่มีภาษาไทย

ป.ล.

Convert pdf to image – แปลงไฟล์ PDF เป็นรูปภาพด้วย Linux บน Windows กัน

จั่วหัวมาแบบนี้ก็อย่าเพิ่งสับสน ณ วันนี้ (พฤษภาคม 2561) Linux กับ Windows เป็นมิตรกันมากกกกกกกกกซึ่งก็ถือเป็นเรื่องที่ดีจริง ๆ สำหรับคนในวงการคอมพิวเตอร์และทั่ว ๆ ไปถือว่าดีกับทุกฝ่ายหล่ะกัน (ลองหาข่าวช่วงก่อนหน้านี้ดูคร่าว ๆ ได้ว่าสังคมสรรเสริญเรื่องนี้กันขนาดไหน) ถ้าใครอยากลองใช้งาน Linux บน Windows ก็ทำตามคร่าว ๆ ประมาณนี้ (แบบละเอียดก็ตามเอกสารตัวนี้ได้เลย)

  1. เปิด PowerShell รันคำสั่งนี้

    รอสักครู่เพื่อให้ระบบเปิดใช้งานฟีเจอร์ “Windows Subsystem for Linux”
  2. เปิด Microsoft Store เพื่อติดตั้ง Ubuntu ต่อได้เลย

    ขนาดไฟล์ก็ไม่ใหญ่มาก
  3. พอติดตั้งเสร็จเราก็เริ่มใช้งานกันได้เลย
  4. จะเห็นได้ว่าเวอร์ชั่นที่ติดตั้งยังเป็น 16.04 (Xenial Xerus) อยู่ ณ ปัจจุบันก็ 18.04 ไปเรียบร้อยแล้ว แต่แค่นี้ก็เพียงพอสำหรับการใช้งานละ ^_^

พอระบบพร้อมสำหรับใช้งานก็มาเริ่มแปลงไฟล์ PDF เป็นรูปภาพกัน (มันมีที่มานิดนึงว่าทำไมต้องใช้วิธีแบบนี้ เนื่องจากเรามีไฟล์ PDF จำนวนมากก จำนวนหนึ่งที่ต้องแปลงเป็นไฟล์รูปภาพแบบด่วน ๆ ลองค้นเครื่องมือบนวินโดวส์ที่เป็นเครื่องมือฟรีรวมถึงออนไลน์ด้วยก็พบว่ามีจำนวนน้อยเกินไป ตัวดี ๆ ก็ Commercial ซะ เศร้าาา และบวกกับความขี้เกียจและเคยชินว่า Linux แปลงไฟล์ตามโจทย์นี้แบบสะดวกเลย แค่นั้นแหล่ะ) เริ่มเลยหล่ะกัน

  1. สร้างไฟล์ Bash Script มา 1 ไฟล์
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    #!/bin/bash
    for file in *.pdf ; do
    convert -verbose -density 300 -quality 100 "${file}" "${file%.*}".png
    done
    #!/bin/bash for file in *.pdf ; do convert -verbose -density 300 -quality 100 "${file}" "${file%.*}".png done
    #!/bin/bash
    for file in *.pdf ; do
      convert -verbose -density 300 -quality 100 "${file}" "${file%.*}".png
    done

    โดยเราใช้โปรแกรมที่ชื่อว่า convert ที่อยู่ใน imagemagick package ก็ให้ติดตั้งโดยใช้คำสั่ง

    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    sudo apt-get install imagemagick
    sudo apt-get install imagemagick
    sudo apt-get install imagemagick

    ซึ่ง Bash script ข้างบนจะทำการแปลงทุกไฟล์ที่นามสกุล *.pdf ใน Directory ปัจจุบัน และบันทึกเป็นไฟล์รูปภาพนามสกุล *.png ส่วน พารามิเตอร์ที่ใช้ ก็ตามไปอ่านต่อที่นี่ได้

  2. ลองทดสอบกัน สมมุติเรามีไฟล์ pdf จำนวนหนึ่ง ตัวอย่างมีไฟล์ 2 ไฟล์ ไฟล์ละ 2 หน้า (ไฟล์เดียวกันนั่นแหล่ะ)

  3. รัน Bash Script เพื่อแปลงไฟล์เป็นรูปภาพซะ

    เราจะได้ไฟล์รูปภาพ 1 ไฟล์ ต่อ 1 หน้ารันลำดับชื่อไฟล์
  4. จบปิ๊ง

Give your Ubuntu 18.04 a flat look with “Qogir” GTK Theme

Qogir is a flat Design theme for GTK 3, GTK 2 and Gnome-Shell which supports GTK 3 and GTK 2 based desktop environments like Gnome, Unity, Budgie, Pantheon, XFCE, Mate.

Based on Arc gtk theme

ป.ล.

  • เดิมเราใช้ Adapta Theme เป็นหลัก
  • เจอธีมนี้เข้าไป สวยจริง ไปตามใน github ได้เลย

Get random 2 rows from each group

การสุ่มตัวอย่าง (Sampling) หมายถึง กระบวนการเลือก “ตัวอย่าง” จาก “ประชากร” เพื่อให้กลุ่มตัวอย่างเป็นตัวแทนของประชากรในการให้ข้อมูล การที่จะเลือกตัวอย่างให้เป็นตัวแทนที่ดีของประชากรได้นั้น จะต้องทำการเลือกแบบสุ่ม (random) หรือเลือกอย่างไม่ลำเอียง (unbias)

นี่เป็นความหมายของการสุ่มตัวอย่าง ซึ่งหลายครั้งเราก็หลีกเลี่ยงไม่ได้ที่จะเลือกข้อมูลบางกลุ่มข้อมูลมาทำงาน ปกติก็ใช้หลักจากข้างบนนั่นแหล่ะเลือกมา (จะใช้วิธี 1-5 ก็เอาที่สบายใจ)

ในกลุ่มมีคำถามนึงน่าสนใจ ถามขึ้นในกลุ่มตามนี้

คร่าว ๆ ก็คืออยากได้กลุ่มข้อมูลมาจำนวนนึงแยกตามรหัส/กลุ่มการวินิจฉัยโรค มาดูอีก 1 วิธีกัน

  1. สร้างตารางทดสอบกัน (เอาตารางเกี่ยวกับผลไม้เนี่ยแหล่ะ เมื่อเช้าจัดมา //แพคเกจแบบนี้โคตรตอบโจทย์เอาจริง ๆ คือกินวันนึงก็ 1-2 ลูกเอง เยอะหน่อยก็ช่วงเล่นกีฬา แล้วกล้วยหอมหวีนึงนี่ก็ใช่ว่าหวีเล็ก ซื้อมาเป็นหวีทีก็กินไม่หมด T_T)

    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    CREATE TABLE fruits
    (`type` varchar(50), `variety` varchar(50), `price` float)
    ;
    INSERT INTO fruits
    (`type`, `variety`, `price`)
    VALUES
    ('apple', 'gala', 2.79),
    ('apple', 'fuji', 0.24),
    ('apple', 'limbertwig', 2.87),
    ('orange', 'valencia', 3.59),
    ('orange', 'navel', 9.36),
    ('pear', 'bradford', 6.05),
    ('pear', 'bartlett', 2.14),
    ('cherry', 'bing', 2.55),
    ('cherry', 'chelan', 6.33);
    CREATE TABLE fruits (`type` varchar(50), `variety` varchar(50), `price` float) ; INSERT INTO fruits (`type`, `variety`, `price`) VALUES ('apple', 'gala', 2.79), ('apple', 'fuji', 0.24), ('apple', 'limbertwig', 2.87), ('orange', 'valencia', 3.59), ('orange', 'navel', 9.36), ('pear', 'bradford', 6.05), ('pear', 'bartlett', 2.14), ('cherry', 'bing', 2.55), ('cherry', 'chelan', 6.33);
    CREATE TABLE fruits
        (`type` varchar(50), `variety` varchar(50), `price` float)
    ;
        
    INSERT INTO fruits
        (`type`, `variety`, `price`)
    VALUES
     ('apple', 'gala', 2.79),
     ('apple', 'fuji', 0.24),
     ('apple', 'limbertwig', 2.87),
     ('orange', 'valencia', 3.59),
     ('orange', 'navel', 9.36),
     ('pear', 'bradford', 6.05),
     ('pear', 'bartlett', 2.14),
     ('cherry', 'bing', 2.55),
     ('cherry', 'chelan', 6.33);

     

  2. ใช้ฟังก์ชั่น RAND() ใน MySQL เพื่อให้ได้ค่าตัวเลขที่ได้จากการสุ่มขึ้นมาและทำการจัดเรียงตามกลุ่ม (กำหนดเงื่อนไข) ในที่นี้เรียงตาม
    `type`
    `type`

    RAND() – Returns a random floating-point value v in the range 0 <= v < 1.0

    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    SELECT
    type,
    variety,
    price,
    RAND()
    FROM fruits
    ORDER BY type, 4
    SELECT type, variety, price, RAND() FROM fruits ORDER BY type, 4
    SELECT
        type,
        variety,
        price,
        RAND()
    FROM fruits
    ORDER BY type, 4

  3. ใส่ลำดับที่ของแต่ละกลุ่มไว้
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    SET @num:=0, @type:='';
    SELECT
    @num:=IF(@type = A.type, @num + 1, 1) as number,
    @type:=A.type as dummy,
    A.*
    FROM (
    SELECT
    type,
    variety,
    price,
    RAND()
    FROM fruits
    ORDER BY type, 4
    ) A
    SET @num:=0, @type:=''; SELECT @num:=IF(@type = A.type, @num + 1, 1) as number, @type:=A.type as dummy, A.* FROM ( SELECT type, variety, price, RAND() FROM fruits ORDER BY type, 4 ) A
    SET @num:=0, @type:='';
    SELECT
        @num:=IF(@type = A.type, @num + 1, 1) as number,
        @type:=A.type as dummy,
        A.*
    FROM (
      SELECT
        type,
        variety,
        price,
        RAND()
      FROM fruits
      ORDER BY type, 4
    ) A

  4. เลือกจำนวนกลุ่มตัวอย่างตามที่ต้องการ (ในคำถามเลือก 2 ตัวอย่าง)
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    ...
    WHERE number <= 2
    ... WHERE number <= 2
    ...
    WHERE number <= 2

    ผลลัพธ์ที่ได้คือรายการที่ได้จากการสุ่มกลุ่มละ 2 ตัวอย่าง

  5. ขอให้สนุกกับเดือนแห่ง QOF จร้าาา

ป.ล.
ลองรันทดสอบได้ที่ http://sqlfiddle.com/#!9/350bc7/6