Tối ưu SQL phần 8: 1 câu chuyện đơn gian về việc cộng chuỗi

Đối với anh em làm về CSDL thì cái công việc được giao là gộp dữ liệu nhiều dòng thành 1 dòng duy nhất với dữ liệu được ngăn cách bởi 1 cái gì đó kì thú như dấu phẩy, chấm phẩy hay bất cứ cái gì có lẽ không phải là việc gì đó xa lạ cho lắm. Tuy vậy thì nhiều anh em cũng chưa thực sự hiểu hết về vấn đề này cho lắm mà chỉ thỉnh thoảng lên mạng rồi copy về chạy cho xong. Chính do đó mà đến lúc cần chỉnh sửa gì lại thì đành bó con mẹ nó tay :)) Do vậy trong cái thời tiết mát mẻ dễ chịu của trưa hè Hà Nội những ngày đầu đông mình quyết định nói lại cái vấn đề mà “ai cũng biết là gì đó” 1 lần nữa :v

Ví giờ anh em có cái bảng Person và bảng Name đi. Giờ muốn lấy danh sách tên mà ngăn dấu , thì anh em thường có 2 cách là

2 cách này nhìn qua thì có lẽ cách thứ 1 có vẻ dễ hiểu hơn với đa số anh em chúng ta vì nó không khác mấy kiểu cộng chuỗi bình thường mà anh em hay dùng với java, C#.

Tuy vậy theo 1 nghiên cứu gần đây (chắc tầm chục năm có lẻ) thì cách thứ nhất mang lại hiệu quả không cao do vấn đề về hiệu năng của nó mang lại cho anh em ta rất là nặng nề :(( Chính vì thế mình sẽ nói về cách thứ 2 là chủ yếu tuy vậy đọc qua thì éo mẹ khó hiểu chết luôn 😐 (Vấn đề hiệu năng anh em có thể đọc qua bài viết https://stackoverflow.com/questions/13639262/optimal-way-to-concatenate-aggregate-strings)

Bây giờ đại loại mình sẽ giải thích về cách thứ 2 như sau:

Đầu tiên là chúng ta sẽ đi vào câu lệnh select nằm ở bên trong có sử dụng xml path. Khi chúng ta sử dụng cái này thì có nghĩa là thằng em SQL sẽ hiểu rằng phải đi qua các cột để ghép thành 1 chuỗi XML với tên thẻ là cái nằm trong cái PATH đó đó. Ví như bây giờ mình không để là PATH(”) mà để là PATH(‘Row’) thì nó sẽ in ra thành

<row>,hoang</row><row>,le</row><row>,nguyen</row>….

Đó chính là lý do chúng ta phải để nó là PATH(”) thì em nó mới hiểu được để in ra thành

,hoang,le,nguyen….

Đấy thế có phải là đẹp đẽ hơn rồi đúng không 😐 Tuy vậy anh em lại nhẹ đưa ánh mắt mà lướt qua dòng kết quả được in ra trên màn hình sẽ thấy nó không được đẹp cho lắm vì vướng cái dấu , ở đầu. Thật là xấu xí phải không? Chắc là SQL cũng phải có cách xử lý chứ nhỉ.

Tất nhiên là phải có cách rồi :3 Chính là cái hàm STUFF đó chứ đâu :v cái hàm này thì hơi hơi khó hiểu 1 chút đại loại như sau

STUFF(chuỗi kí tự, vị trí bắt đầu, số lượng bỏ đi, kí tự thay thế)

Ví dụ như ta có chuỗi “Nguyễn Lê Hoàng” thì thay thế cái Lê thành Ngọc. Anh em đơn giản dúng với hàm STUFF như sau,

SELECT STUFF (‘Nguyễn Lê Hoàng′,8,2,’Ngọc’)

Số 8 ở đây là số bắt đầu của chữ Lê (kí tự L đó)

Số 2 ở đây là độ dài của chữ Lê

Sau khi loại bỏ được chữ Lê đi thì nhét cái chữ Ngọc vào thôi :3

Với ý tưởng như vậy thì khi có chuỗi ‘,hoang,le,nguyen’ anh em ta muốn bỏ cái dấu , ở đâu thì vị trí bắt đầu là 1 rồi, số lượng đáp đi tất nhiên cũng là 1 luôn, và thay bằng kí tự trắng thôi chứ đâu :3 Chính vì thế mới có cái STUFF(…,1,1,”) đó 😛

Giờ thì anh em chắc đã hiểu tưởng tận và thực hành với lệnh cộng chuỗi trong SQL rồi chứ. Vậy thì xúc tiến đi chứ còn chần chờ gì nữa :3

PS: Anh em lưu ý khi sử dụng FOR XML PATH để đọc giá trị trong thẻ XML thì ta hay dùng cái data() ví như

SELECT name + ‘,’ as ‘data()’ FROm person FOR XML PATH (”)

Mình dùng cái này xong thì chuỗi cộng ra sẽ có dấu space ở cuối  chính vì thế nếu anh em nào không có nhu cầu sử dụng thì đừng dùng nhé 😐

Advertisements

One thought on “Tối ưu SQL phần 8: 1 câu chuyện đơn gian về việc cộng chuỗi

  1. Pingback: Tối ưu SQL (phần 9): tính tổng các dòng | Code, code and more code

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s