Menu

Showing posts with label sql. Show all posts
Showing posts with label sql. Show all posts

Wednesday, April 8, 2020

[Database - MySQL] วิธีการแก้ปัญหา Syntax Error เมื่อทำการสร้าง Procedure
[Database - MySQL] How to Fix Syntax Error when Creating a Procedure

สมมติว่า เราต้องการสร้าง procedure ด้วย SQL statement ข้างล่างนี้
CREATE PROCEDURE `my_procedure` (IN `_year` INT, IN `_month` INT)
    NO SQL
BEGIN
    SELECT * FROM my_table WHERE year = `_year`and month = `_month`;
END;
อย่างไรก็ตาม statement นี้ไม่สามารถรันได้ทุกฐานข้อมูล

บางฐานข้อมูลจะแสดงข้อผิดพลาดตามรูปข้างล่างนี้


Thursday, August 29, 2019

[Laravel - Exception] ระวังข้อผิดพลาด "Prepared statement contains too many placeholders" หากมีการ Bulk Insert ข้อมูลจำนวนมาก
[Laravel - Exception] Warning: "Prepared statement contains too many placeholders" Exception if Bulk Insert Large Data

การทำ bulk insert หรือการ insert ข้อมูลทีละเยอะๆ สามารถช่วยลดจำนวนการยิง query หลายๆรอบได้ ซึ่งส่งผลให้เวลาในการทำงานลดลงอย่างเห็นได้ชัด โดยเฉพาะอย่างยิ่ง เมื่อ Database อยู่คนละเครื่อง Server

แต่... อย่าเพิ่งคิดนะครับว่า เราจะยิงข้อมูลเป็นก้อนใหญ่ๆไปเลยทีเดียวได้

เพราะว่ามันก็มี limit ในเรื่องของ placeholder อยู่เหมือนกัน ซึ่งถ้าหากเราส่งข้อมูลก้อนใหญ่เกินไปก็จะได้ error นี้กลับมา
PDOException: SQLSTATE[HY000]: General error: 1390 Prepared statement contains too many placeholders in /var/www/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:77
แล้ว placeholder มาจากไหน?

Thursday, May 30, 2019

[Database - SQL] วิธีคำนวณระยะทางระหว่างพิกัด (Latitude, Longitude) 2 พิกัด
[Database - SQL] How to Calculate Distance between 2 Points of (Latitude, Longitude)

เนื่องจากผิวโลกมีความโค้ง จึงต้องใช้ haversine formula ในการคำนวณระยะทางที่สั้นที่สุดระหว่างพิกัดสองพิกัดบนผิวโลก

สมมติว่า ตาราง location ประกอบด้วยคอลัมน์ lat และ lon ที่เก็บค่า Latitude และ Longitude ตามลำดับของแต่ละพิกัด และพิกัดที่สนใจอยู่ที่ตำแหน่ง ([lat0], [lon0])

เราสามารถค้นหาพิกัดที่อยู่ใกล้เคียงกับพิกัดที่เราสนใจ ภายในรัศมี 1 กิโลเมตร โดยใช้ SQL ดังต่อไปนี้

SELECT *, 6373  * 2 * ATAN2(
    SQRT(
        POW(SIN((lat - [lat0]) * PI() / 180 / 2), 2) +
        COS(ABS([lat0]) * PI() / 180) *
        COS(ABS(lat) * PI() / 180) *
        POW(SIN((lon - [lon0]) * PI() / 180 / 2), 2)
    ),
    SQRT(1-(
        POW(SIN((lat - [lat0]) * PI() / 180 / 2), 2) +
        COS(ABS([lat0]) * PI() / 180) *
        COS(ABS(lat) * PI() / 180) *
        POW(SIN((lon - [lon0]) * PI() / 180 / 2), 2))
    )
) as dist
FROM `location`
HAVING  dist < 1 
ORDER BY dist

โดยที่
  •     6373 เป็นรัศมีของโลก มีหน่วยเป็นกิโลเมตร
  •     lat เป็นค่า Latitude ของ record ในตาราง location
  •     lon เป็นค่า Longitude ของ record ในตาราง location
  •     [lat0] เป็นค่า Latitude ของพิกัดที่เราสนใจ
  •     [lon0] เป็นค่า Longitude ของพิกัดที่เราสนใจ
  •     dist เป็นระยะทางระหว่างพิกัดที่เราสนใจกับพิกัดของ record ในตาราง location มีหน่วยเป็นกิโลเมตร

Tuesday, April 23, 2019

[Database - SQL] วิธีการ Query หา Record ที่มีค่ามากที่สุดหรือน้อยที่สุด
[Database - SQL] How to Query a Record that Has Maximum or Minimum Value

สมมติว่า user_login เป็นตารางในฐานข้อมูลที่มีคอลัมน์ login_at สำหรับเก็บวันเวลาที่ผู้ใช้งาน login เข้าใช้งานระบบ

ในกรณีที่เราต้องการหา record ของการ login เข้าใช้งานล่าสุดของผู้ใช้งานทุกคน (login_at มีค่ามากที่สุด) เราสามารถใช้คำสั่ง SQL ตามด้านล่างนี้ได้เลย
SELECT * 
FROM user_login 
WHERE EXISTS (
    SELECT 1
    FROM user_login AS ul
    GROUP BY user_id
    HAVING user_id = users_login.user_id AND
        MAX(login_at) = user_login.login_at
)
ในทางตรงกันข้าม ถ้าเราต้องการหา record ของการ login เข้าใช้งานครั้งแรกสุดของผู้ใช้งานทุกคน (login_at มีค่าน้อยที่สุด) เราสามารถใช้คำสั่ง SQL ตามด้านล่างนี้ได้เลย
SELECT * 
FROM user_login 
WHERE EXISTS (
    SELECT 1
    FROM user_login AS ul
    GROUP BY user_id
    HAVING user_id = users_login.user_id AND
        MIN(login_at) = user_login.login_at
)