2012-02-21 5 views
4

메신저 내 쿼리에 대한 MySQL의 비트 연산을 사용하려고하고 내가이 예를 가지고 : 지금PHP에서 MySQL 비트 연산을 사용하는 방법?

table1 
id  ptid 
1  3 
2  20 
3  66 
4  6 

table2 
id  types 
1  music 
2  art 
4  pictures 
8  video 
16  art2 
32  actor 
64  movies 
128 .. 
... 

, table1에서 id = 3는 '66'입니다, 마녀는 것을 의미 64 or movies2 or art

하지만

그는 또한 32 or actor2 or art ??

내 혼란이 어디 있는지 알기를 바랍니다. 내가 원하는 결과를 어떻게 제어 할 수 있습니까? 이 경우 64 or movies2 or art이 필요합니다.

하지만 가끔은 내가 table2에서 세 id'stable1

어떤 아이디어에서 id에 속하는 싶어?

감사

+2

** 잘못된 데이터 모델입니다. –

+0

호기심에서, 왜 id -> ptid 관계를 개별적으로 추적하는 테이블을 사용하지 않았습니까? – jprofitt

+0

두 테이블을 결합하기 위해 MySQL에서 비트 연산을 사용 하시겠습니까 ??? 내 눈! 고글 아무것도 안합니다! 그러나 @jprofitt가 말했듯이, 더 표준적인 많은 - 많은 관계 모델을 사용하는 것이 좋을까요? –

답변

10

사용하여 비트 OR

다음 쿼리는 66 테이블 2에서 모든 항목을 반환

SELECT * 
FROM table2 
WHERE id | 66 = 66 

그러나 32 + 32 = 64

?

32 + 32 = 64이지만 영향을 미치지 않습니다.

여기서 이진 64이다 :

여기
01000000 

이진 32이다 : 바이너리 여기

00100000 

의 2

00000010 

그것은 우리가 사용하는 (1)의 위치의 이 경우가 아니라 값입니다. 두 가지가 없을 것입니다. 각 플래그는 on 또는 off입니다.

2 진수는 66입니다.비트를 사용

01000010 

대신 쿼리를 작성하는 또 다른 방법으로 또는

비트와이 같다 : 64, 2가 켜져 있는지없는 32주의

SELECT * 
FROM table 
WHERE id & 66 <> 0 

0 = false이 MySQL에 이르기 때문에, 다음과 같이 더 줄여서 표현할 수 있습니다 :

+0

이제 알겠습니다. 감사 – Patrioticcow

4
select * from table2 where id & 66 
3

MySQL에서 비트 연산을 수행하는 방법에 대한 질문에 대한 답변이 있지만 최적의 데이터 모델이 아닌 이유에 대한 의견의 하위 질문은 여전히 ​​뛰어난 상태입니다.

주어진 예제에는 두 개의 테이블이 있습니다. 하나는 비트 마스크가 있고 다른 하나는 각 비트가 나타내는 것을 분해합니다. 그 의미는 어떤 시점에서 여러 비트의 의미를 반환하거나 표시하기 위해 두 테이블을 서로 조인해야한다는 것입니다.

이 조인은 명시 적이어야합니다 (예 :

SELECT * 
FROM Table1 
    INNER JOIN TABLE2 
     ON table1.ptid & table2.id <> 0 

또는 당신이 당신의 응용 프로그램에 table1에서 데이터를 선택하고, 예를 들어 비트 마스크 값을 참조하기위한 두 번째 전화를 걸 수있는 위치 암시 그들이입니다 "스 SARGable"하지 않기 때문에

SELECT * 
FROM table2 
WHERE id & $id <> 0 

이러한 옵션 중 어느 것도

아이디어 있으며, 데이터베이스 검색 인수를 구성 할 수 없습니다. 따라서 인덱스를 사용하여 쿼리를 최적화 할 수 없습니다. 쿼리 비용은 테이블의 모든 행에 대해 DB를 사용하여 표현식을 계산하고 평가해야하므로 인덱스를 활용할 수 없습니다. 이것은 매우 메모리, CPU 및 I/O 집약적으로 매우 빠르게되고 테이블 구조를 근본적으로 변경하지 않고는 최적화 할 수 없습니다.

쿼리를 완벽하게 수행 할 수 없다는 것 외에도 데이터를 읽거나 데이터를보고하는 것이 어색 할 수 있으며 더 많은 비트를 추가 할 가능성도 있습니다 (8 비트 열의 64 개 값은 이제 좋을 수도 있습니다 항상 이해할 수있는 것은 아니지만 시스템을 이해하기 어렵게 만들고이 디자인이 첫 번째 정규 형식을 위반한다고 주장합니다.

데이터베이스의 비트 마스크를 사용하는 것은 종종 잘못된 디자인의 징조이지만 괜찮 으면

이러한 유형의 관계를 구현하는 일반적인 방법은 t와 비슷합니다. 그의 :

table1 
Id  Val1   Val2 
--------------------------- 
1   ABC   DEF 
2   ABC   DEF 
3   ABC   DEF 
4   ABC   DEF 
5   ABC   DEF 
6   ABC   DEF 

table2 
id  types 
------------- 
1  music 
2  art 
3  pictures 
4  video 
5  art2 
6  actor 
7  movies 

table1-table2-relationshitp 
table1ID Table2ID 
--------------------- 
1   1 
1   2 
2   3 
2   5 
3   2 
3   7 
... 

그리고 당신은 일반적으로 인덱스 복합 인덱스로 관계 테이블에 모두 열 (나는 보통 치료 것,이 테이블의 액세스 패턴에 따라 데이터 thusly 히

SELECT table1.*, table2.types 
FROM table1 
    INNER JOIN table1-table2-relationship 
      ON table1.id = table1-table2-relationship.table1id 
    INNER JOIN table2 
      ON table1-table2-relationship.table2.id = table2.id 

를 조회 할 이들 인덱스는 복합 기본 키로 사용됩니다.)이 인덱스는 데이터베이스가 관계 테이블의 관련 행을 빠르게 찾은 다음 table2의 관련 행을 탐색합니다.

0

Marcus Adams의 답을 가지고 놀고 나면 비트 연산을 사용하여 두 테이블을 조인하는 방법을 이해하는 데 도움이되는 또 다른 예를 제공 할 것이라고 생각했습니다.

모음 표를 정의하는 다음 샘플 데이터와 그 단어에있는 모음을 나타내는 단일 값이있는 단어 표를 생각해보십시오.

# List every word with its vowels. 
select Word, Vowels, Letter, Id as 'Vowel Id' 
from (
    select * 
    from Words 
) w 
join Vowels v 
where v.Id | w.Vowels = w.Vowels 
order by Word, Letter; 

을 그리고 물론 우리는 내부 쿼리에 어떤 조건을 적용 할 수 있습니다

# Create sample tables. 
drop temporary table if exists Vowels; 
create temporary table Vowels 
(
    Id int, 
    Letter varchar(1) 
); 
drop temporary table if exists Words; 
create temporary table Words 
(
    Word varchar(20), 
    Vowels int 
); 

# Insert sample data. 
insert into Vowels 
    select 1, 'a' union all 
    select 2, 'e' union all 
    select 4, 'i' union all 
    select 8, 'o' union all 
    select 16, 'u'; 
insert into Words 
    select 'foo',   8 union all 
    select 'hello',   10 union all 
    select 'language',  19 union all 
    select 'programming', 13 union all 
    select 'computer',  26;  

우리는 지금 이렇게 같이 Word 테이블에 Vowel 테이블을 가입 할 수 있습니다.

# List the letters for just the words with a length < 6 
select Letter 
from (
    select * 
    from Words 
    where length(Word) < 6 
) w 
join Vowels v 
where v.Id | w.Vowels = w.Vowels 
order by Word, Letter 
관련 문제