2014-06-26 17 views
1

已知以下數據:MySQL的 - 查詢整數按位場分爲布爾列的每一位

mysql> select * from test2; 
+-------+--------+ 
| name | status | 
+-------+--------+ 
| bob |  0 | 
| jim |  2 | 
| karen |  5 | 
| jane |  1 | 
| roy |  7 | 
+-------+--------+ 

我要拿出一個查詢將拆分出來的狀態列的值轉換爲整數的每個單獨位的僞布爾值列。

我現在要做的是讓應用程序生成使用case語句和位和運營商爲每一列得到的結果,像這樣的查詢:

mysql> select 
    ->  name, 
    ->  (case when (status & 1) then 'yes' else 'no' end) as bit1, 
    ->  (case when (status & 2) then 'yes' else 'no' end) as bit2, 
    ->  (case when (status & 4) then 'yes' else 'no' end) as bit4, 
    ->  (case when (status & 8) then 'yes' else 'no' end) as bit8 
    -> from test2; 
+-------+------+------+------+------+ 
| name | bit1 | bit2 | bit4 | bit8 | 
+-------+------+------+------+------+ 
| bob | no | no | no | no | 
| jim | no | yes | no | no | 
| karen | yes | no | yes | no | 
| jane | yes | no | no | no | 
| roy | yes | yes | yes | no | 
+-------+------+------+------+------+ 
5 rows in set (0.00 sec) 

現在這個工作的,這樣做因爲沒有子查詢或聯接,所以效率不高,但它不是很優雅。

我想要一個更優雅的解決方案來動態執行此操作,而不必創建case語句並測試每一位。

這是隻有幾位數據的示例數據,但在實現中,將會有數萬行,並且可以設置更多的位。

加成:

基地產生的列(列名稱和測試)關閉含有每個位的定義如下所示的表中的:

mysql> select * from bit_spec; 
+-----+------+ 
| bit | desc | 
+-----+------+ 
| 1 | bit1 | 
| 2 | bit2 | 
| 4 | bit3 | 
| 8 | bit4 | 
+-----+------+ 

目前,應用程序處理這並不是一個強硬的要求,而是由MySQL服務器來完成這個處理,但如果是這樣的話,這將是有利的。

這裏是SQL Fiddle包含示例數據,示例位定義表和我當前的解決方案。

回答

1

這可以通過將每個用戶/位/值組合檢索到行中,然後將這些行轉換爲列來實現。

select 
    name, 
    `desc`, 
    ((status & bit) > 0) value 
from test2, bit_spec 

上述查詢產生的結果在下面的格式

name | desc | value 
bob | bit1 | 0 
bob | bit2 | 0 

從這裏我們可以樞轉的結果爲所需的格式,其中每個desc/value對被轉換爲一個名爲desc與值value柱。

使用下面的帖子https://stackoverflow.com/a/12005676/3574819

SET @sql = NULL; 
SELECT 
    GROUP_CONCAT(DISTINCT 
    CONCAT(
     'SUM(case when `desc` = ''', 
     `desc`, 
     ''' then value end) AS ', 
     replace(`desc`, ' ', '') 
    ) 
) INTO @sql 
from bit_spec; 

SET @sql = CONCAT('SELECT t1.name, ', @sql, ' from 
(select 
    name, 
    `desc`, 
    ((status & bit) > 0) value 
from test2, bit_spec) t1 
group by t1.name 
order by t1.name'); 

PREPARE stmt FROM @sql; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 

http://sqlfiddle.com/#!2/5f6d0/22

NAME  BIT1 BIT2 BIT3 BIT4 
bob   0  0  0  0 
jane  1  0  0  0 
jim   0  1  0  0 
karen  1  0  1  0 
roy   1  1  1  0 

旁註

如果需要通過許可(搜索即表明已BIT1 &第2位,但並不是所有的用戶bit3),那麼我不建議存儲您的權限a因爲db不能爲結果建立索引。在這種情況下,由列(user_id,permission_id)組成的索引連接表會產生更快的結果。

+0

它主要用於報告的目的,將會有一些針對它的測試,但是有一些有趣的方法可以解決MySQL中按位字段的效率問題[1],所以我並不完全擔心關於它。你的答案看起來不錯,我很可能會在做一些測試後接受它。 [1] http://explainextended.com/2009/10/01/bitwise-operations-and-indexes/ –