2012-02-02 29 views
6

tôi phải thực hiện truy vấn chọn trong bảng đăng nơi có một bit cụ thể của một số nguyên được đặt. Số nguyên đại diện cho một tập hợp các danh mục trong một bitmask: Ví dụ:hàng mySQL SELECT trong đó một bit cụ thể của một số nguyên được đặt

1 => health 
2 => marketing 
3 => personal 
4 => music 
5 => video 
6 => design 
7 => fashion 
8 => ...... 

dụ dữ liệu:

id | categories | title 
1 | 11   | bla bla 
2 | 48   | blabla, too 

Tôi cần một truy vấn mysql mà chọn đăng, được đánh dấu bằng một loại cụ thể. Hãy nói rằng "tất cả các thông tin đăng video" Điều này có nghĩa tôi cần một bộ kết quả của thông tin đăng nơi các bit thứ 5 của cột catgories được thiết lập (ví dụ 16,17,48 ....)

SELECT * FROM postings WHERE ....???? 

Bất kỳ ý tưởng?

+1

Tại sao không chỉ là một bảng bổ sung ở giữa: categories_postings? Đó sẽ là một giải pháp chứng minh tương lai hơn vì điều này dường như chỉ là một cơ sở dữ liệu nhiều loại tiêu chuẩn? –

+1

Tôi đồng ý với Luc, sẽ dễ dàng hơn để duy trì một bảng phụ gọi là categories_groups, có cấu trúc như: id, category_group_name, health, marketing, personal, music ... và sẽ giữ "0"/"1" trong mỗi danh mục để đánh dấu xem danh mục này thuộc về nhóm này hay không. Bằng cách này, nó cũng sẽ dễ dàng hơn nhiều để tổng hợp số lượng nhóm bao gồm danh mục "sức khỏe". – alfasin

+0

@Luc - cả hai bạn đều đúng - thực tế là, dữ liệu được xuất bản bởi ứng dụng bên ngoài nơi tôi không thể thực hiện bất kỳ thay đổi nào. Một mối quan hệ nhiều-nhiều sẽ là giải pháp tốt nhất .... – derRobert

Trả lời

9

Bạn có thể sử dụng bitwise nhà khai thác như thế này. Đối với video (bit 5):

WHERE categories & 16 = 16 

thay thế giá trị 16 sử dụng các giá trị sau cho mỗi bit:

1 = 1 
2 = 2 
3 = 4 
4 = 8 
5 = 16 
6 = 32 
7 = 64 
8 = 128 

này đi từ bit ít quan trọng đến cao nhất, đó là đối diện của đường nhất các lập trình viên suy nghĩ. Họ cũng bắt đầu từ số không.

+0

Các ánh xạ ở trên có thể được đơn giản hóa thành: bitVal = 2^(i-1), trong đó i là giá trị chỉ mục ở bên trái. Vì vậy, ví dụ, 16 = 2^(5-1). –

2

Làm thế nào về

SELECT * FROM postings WHERE (categories & 16) > 0; -- 16 is 5th bit over 

Một vấn đề với điều này là có thể bạn sẽ không đánh chỉ số một, vì vậy bạn có thể chạy vào các vấn đề về hiệu suất nếu đó là một lượng lớn dữ liệu.

Một số cơ sở dữ liệu nhất định (như PostgreSQL) cho phép bạn xác định chỉ mục trên một biểu thức như thế này. Tôi không chắc liệu mySQL có tính năng này hay không. Nếu điều này quan trọng, bạn có thể muốn xem xét chia nhỏ các cột này thành các cột Boolean riêng biệt hoặc một bảng mới.

-1

SQL (không chỉ mySQL) không phù hợp cho hoạt động bitwise. Nếu bạn làm một chút và bạn sẽ bắt buộc quét bảng vì SQL sẽ không thể sử dụng bất kỳ chỉ mục nào và sẽ phải kiểm tra từng hàng một tại một thời điểm.

Sẽ tốt hơn nếu bạn tạo một bảng "Danh mục" riêng biệt và một bảng Các danh mục đăng bài nhiều người được lập chỉ mục phù hợp để kết nối cả hai.

CẬP NHẬT

Đối với những người khẳng định rằng lĩnh vực bitmap không phải là một vấn đề, nó giúp để kiểm tra Joe Celko của BIT of a Problem. Ở cuối bài viết là một danh sách các vấn đề nghiêm trọng gây ra bởi bitmap.

Về nhận xét rằng một tuyên bố chăn không thể đúng, lưu ý # 10 - nó phá vỡ 1NF nên có, lĩnh vực bitmap là xấu:

  1. Các dữ liệu không thể đọc được. ...
  2. Ràng buộc là b #### để viết ....
  3. Bạn được giới hạn hai giá trị cho mỗi trường. Điều đó rất hạn chế; ngay cả mã ISO cũng không thể phù hợp với một cột như vậy ...
  4. Không có phần tử thời gian nào cho mặt nạ bit (hoặc các cờ bit đơn). Ví dụ, một lá cờ "is_legal_adult_flg" ... Một NGÀY cho ngày sinh (chỉ 3 byte) sẽ giữ thực tế hoàn chỉnh và cho chúng tôi tính toán những gì chúng ta cần biết; nó sẽ luôn luôn là chính xác, quá. ...
  5. Bạn sẽ thấy rằng việc sử dụng cờ sẽ có xu hướng phân chia trạng thái của thực thể qua nhiều bảng ....
  6. Cờ bit mời dự phòng. Trong hệ thống tôi vừa đề cập, chúng tôi đã có "is_active_flg" và "is_completed_flg" trong cùng một bảng. Một cuộc đấu giá hoàn thành không hoạt động và ngược lại. Nó là cùng một thực tế trong hai lá cờ. Tâm lý con người (và ngôn ngữ tiếng Anh) thích nghe một từ ngữ khẳng định (nhớ bài hát cũ "Vâng, chúng tôi không có chuối ngày hôm nay!"?). Tất cả các cờ bit này và xác thực chuỗi được thay thế bằng hai bộ bảng chuyển đổi trạng thái, một cho các giá thầu và một cho các lô hàng. Để biết chi tiết về các hạn chế chuyển tiếp trạng thái. Lịch sử của mỗi phiên đấu giá hiện tại ở một nơi và phải tuân thủ các quy tắc kinh doanh.
  7. Bởi thời gian bạn tháo rời một cột mặt nạ bit, và ném ra các lĩnh vực bạn không cần hiệu suất sẽ không được cải thiện trên các loại dữ liệu đơn giản.
  8. Phân nhóm và đặt hàng trên các trường riêng lẻ là một nỗi đau thực sự. Thử nó.
  9. Bạn phải lập chỉ mục toàn bộ cột, vì vậy trừ khi bạn may mắn và đưa chúng theo đúng thứ tự, bạn bị kẹt với việc quét bảng.
  10. Vì mặt nạ bit không có trong Biểu mẫu thông thường đầu tiên (1NF), bạn có tất cả các dị thường mà chúng tôi muốn tránh trong RDBMS.

Tôi cũng sẽ thêm, điều gì về NULL? Còn thiếu cờ? Điều gì xảy ra nếu một cái gì đó không đúng hay sai?

Cuối cùng, liên quan đến yêu cầu nén, hầu hết các cơ sở dữ liệu gói các trường bit thành byte và int nội bộ. Trường bitmap không cung cấp bất kỳ loại nén nào trong trường hợp này. Các cơ sở dữ liệu khác (ví dụ PostgreSQL) thực sự có một kiểu Boolean có thể là true/false/unknown. Có thể mất 1 byte nhưng đó là không phải nhiều bộ nhớ và tính năng nén trong suốt khả dụng nếu bảng quá lớn.

Thực tế, nếu một bảng lớn thì các vấn đề về lĩnh vực bitmap trở nên nghiêm trọng hơn rất nhiều. Tiết kiệm một vài MB trong bảng GB sẽ không đạt được nếu bạn buộc phải sử dụng tính năng quét bảng hoặc nếu bạn mất khả năng nhóm

+0

Điều này là quá nhiều của một tuyên bố chăn là chính xác. Tuy nhiên, bạn sẽ không thể thực hiện quét chỉ mục trong các trường bitwise, chúng có thể hữu ích và dẫn đến giảm kích thước lưu trữ lớn hoặc tăng tốc truy vấn tùy thuộc vào những gì bạn đang thực hiện. – delrox

+1

Nếu tìm kiếm của bạn chỉ sử dụng trường bitmapped cho "dặm cuối cùng" - nói cách khác bạn đã thu hẹp tìm kiếm lớn hơn xuống tới vài trăm bản ghi hoặc sử dụng các trường/chỉ mục khác - thì không có nhiều về vấn đề về sự hài lòng cần quan tâm. Đối với các trường dữ liệu tĩnh bitmap mạnh, như những người khác đã đề cập, một dạng nén dữ liệu tốt. (Chúng tôi sẽ không thêm một ngày mới trong tuần cũng như bất kỳ giờ mới nào trong một ngày bất kỳ lúc nào chẳng hạn ...) – Techmag

+1

@Techmag thực sự, không. Các DBA thường ghét các trường bitmap vì chúng gây ra các lỗi * LOT *, thực hiện một trong số chúng. Chúng làm cho dữ liệu không thể đọc được, ngăn chặn việc sử dụng các ràng buộc và nhiều hơn nữa. Kiểm tra [BIT của một vấn đề] của Joe Celko (https://www.simple-talk.com/sql/t-sql-programming/bit-of-a-problem/). Những gì bạn gọi là nén, đặc biệt là cho ngày, sẽ được thay thế bằng một loại đơn giản hoặc giá trị enum. Trong thực tế, bạn có thể tranh luận về nén * chỉ * nếu bạn có thể sử dụng tất cả các bit trên trường sao lưu. Nếu không, bạn sẽ lãng phí, ví dụ 7 bit trong số 16 bit bit của –

Các vấn đề liên quan