2

MySQLクエリでこれを行うための明確で簡単な方法がわかりません。スキーマは次のようになります。

CREATE TABLE users (
    id VARCHAR(20),
    col SET('read', 'write', 'edit', 'delete'),
);

readそして、(他の値セットに関係なく)とprivsを持つすべてのユーザーに対してクエリを実行したい場合write、行を取得するために思いついた唯一のクエリは次のとおりです。

SELECT id, privs
FROM users WHERE
FIND_IN_SET('read',privs) > 0 AND 
FIND_IN_SET('write',privs) > 0

これを単純化する方法はありませんか?何かのようなもの:

SELECT id, privs
FROM users WHERE
privs('read' & 'write')

仮説としては、より洗練されたビット ロジックを使用したいのですが、SET型を使用するときにこれを達成する唯一の方法が実際の例であるかどうかを知りたいです。

4

2 に答える 2

1

値は、create table ステートメントと同じ順序で格納されます。

あなたの場合:

        decimal   |   binary
read    1         |   0001
write   2         |   0010
edit    4         |   0100
delete  8         |   1000

を追加して列を「変換」することで、10 進数値を取得できます0

したがって、読み取りと書き込みを取得するには、次のようにします。

SELECT id, privs
FROM users 
WHERE
privs+0 = 3;

詳しくはこちらをご覧ください。

アップデート:

privs+0 = 3「読み書き」のみを返します。

また、前述したように、エントリに値が割り当てられる頻度に関係なく、値は順番に格納されます。

したがって、次のようにすることもできます。

SELECT id, privs
FROM users 
WHERE
privs = 'read,write';

そして、少なくとも読み取りと書き込み、可能であればそれ以上が必要な場合:

SELECT id, privs
FROM users 
WHERE
privs LIKE 'read,write%';
于 2012-04-16T11:09:05.693 に答える
1

MySQL でそれを行う洗練された方法がない場合は、これで解決します。少なくとも、すべてのセット要素のビット フィールドの位置/値を手動で記憶する必要はありません。よりニーモニックな文字列を使用することもできます。CROSS JOIN のみを使用します。

SELECT u.id, u.col
FROM users u

CROSS JOIN
(
  select sum(val) as bit_result from
  (
  SELECT 'read' as txt,1 as val
  union
  SELECT 'write' as txt,2 as val
  union
  SELECT 'edit' as txt,4 as val
  union
  SELECT 'delete' as txt,8 as val
  ) as x
  where txt in ('read','write')
) as z

WHERE u.col & z.bit_result = z.bit_result

ソースデータ:

CREATE TABLE users (
    id VARCHAR(20),
    col SET('read', 'write', 'edit', 'delete')
);

insert into users(id,col)
values ('hello','read,write');

insert into users(id,col)
values ('hola','read,delete,write');

insert into users(id,col)
values ('yeah','delete,write');

出力: 'hello' と 'hola'

http://sqlfiddle.com/#!2/56070/41

于 2012-04-16T13:04:22.373 に答える