비트별 그룹 기능을 수행할 수 있습니까?
테이블에 비트 플래그가 포함된 필드가 있습니다.예를 들어 세 가지 플래그가 있다고 가정해 보겠습니다.4 => read, 2 => write, 1 => execute그리고 테이블은 이렇게 생겼습니다.*:
user_id | file | permissions
-----------+--------+---------------
1 | a.txt | 6 ( <-- 6 = 4 + 2 = read + write)
1 | b.txt | 4 ( <-- 4 = 4 = read)
2 | a.txt | 4
2 | c.exe | 1 ( <-- 1 = execute)
레코드에 특정 플래그 집합(예: 쓰기)이 있는 모든 사용자를 찾고 싶습니다.하나의 쿼리에서 이 작업을 수행하려면 사용자의 모든 권한을 함께 OR하면 권한의 "합계"에 해당하는 단일 값을 얻을 수 있다고 생각했습니다.
user_id | all_perms
-----------+-------------
1 | 6 (<-- 6 | 4 = 6)
2 | 5 (<-- 4 | 1 = 5)
*내 실제 테이블은 파일이나 파일 권한과 관련이 없습니다. 예에 불과합니다.
제가 이것을 한 문장으로 수행할 수 있는 방법이 있습니까?GROUP BY를 사용하는 일반 집계 함수와 매우 유사합니다.
SELECT user_id, SUM(permissions) as all_perms
FROM permissions
GROUP BY user_id
...하지만 분명히 SUM 대신에 어떤 마법적인 "비트와이즈-or" 기능이 있습니다.그런 거 아는 사람?
(그리고 보너스 포인트의 경우 오라클에서도 작동합니까?)
MySQL:
SELECT user_id, BIT_OR(permissions) as all_perms
FROM permissions
GROUP BY user_id
아, 또 다른 질문 중 하나는 질문을 한 지 5분 후에 답을 찾는 것입니다.승인된 답변은 MySQL 구현에 적용됩니다.
Radino의 블로그에서 확인한 오라클 솔루션을 사용하는 방법은 다음과 같습니다.
객체를 생성하면...
CREATE OR REPLACE TYPE bitor_impl AS OBJECT
(
bitor NUMBER,
STATIC FUNCTION ODCIAggregateInitialize(ctx IN OUT bitor_impl) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateIterate(SELF IN OUT bitor_impl,
VALUE IN NUMBER) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateMerge(SELF IN OUT bitor_impl,
ctx2 IN bitor_impl) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateTerminate(SELF IN OUT bitor_impl,
returnvalue OUT NUMBER,
flags IN NUMBER) RETURN NUMBER
)
/
CREATE OR REPLACE TYPE BODY bitor_impl IS
STATIC FUNCTION ODCIAggregateInitialize(ctx IN OUT bitor_impl) RETURN NUMBER IS
BEGIN
ctx := bitor_impl(0);
RETURN ODCIConst.Success;
END ODCIAggregateInitialize;
MEMBER FUNCTION ODCIAggregateIterate(SELF IN OUT bitor_impl,
VALUE IN NUMBER) RETURN NUMBER IS
BEGIN
SELF.bitor := SELF.bitor + VALUE - bitand(SELF.bitor, VALUE);
RETURN ODCIConst.Success;
END ODCIAggregateIterate;
MEMBER FUNCTION ODCIAggregateMerge(SELF IN OUT bitor_impl,
ctx2 IN bitor_impl) RETURN NUMBER IS
BEGIN
SELF.bitor := SELF.bitor + ctx2.bitor - bitand(SELF.bitor, ctx2.bitor);
RETURN ODCIConst.Success;
END ODCIAggregateMerge;
MEMBER FUNCTION ODCIAggregateTerminate(SELF IN OUT bitor_impl,
returnvalue OUT NUMBER,
flags IN NUMBER) RETURN NUMBER IS
BEGIN
returnvalue := SELF.bitor;
RETURN ODCIConst.Success;
END ODCIAggregateTerminate;
END;
/
...그런 다음 자체 집계 함수를 정의합니다.
CREATE OR REPLACE FUNCTION bitoragg(x IN NUMBER) RETURN NUMBER
PARALLEL_ENABLE
AGGREGATE USING bitor_impl;
/
용도:
SELECT user_id, bitoragg(permissions) FROM perms GROUP BY user_id
그리고 조금 현명하게 할 수도 있고, 아니면...
FUNCTION BITOR(x IN NUMBER, y IN NUMBER)
RETURN NUMBER
AS
BEGIN
RETURN x + y - BITAND(x,y);
END;
가능한 권한 구성 요소(1, 2 및 4)를 사전에 알아야 하지만(따라서 유지 관리가 더 어렵습니다), 이 방법은 매우 간단하며 다음과 같습니다.
SELECT user_id,
MAX(BITAND(permissions, 1)) +
MAX(BITAND(permissions, 2)) +
MAX(BITAND(permissions, 4)) all_perms
FROM permissions
GROUP BY user_id
레코드에 특정 플래그 집합(예: 쓰기)이 있는 모든 사용자를 찾고 싶습니다.
간단히 말해서 무엇이 문제입니까?
SELECT DISTINCT User_ID
FROM Permissions
WHERE permissions & 2 = 2
언급URL : https://stackoverflow.com/questions/1397913/is-it-possible-to-perform-a-bitwise-group-function
'programing' 카테고리의 다른 글
| Vuejs에서 무한한 시계 루프를 찾을 방법이 있습니까? (0) | 2023.07.06 |
|---|---|
| 대형 판다 데이터 프레임 분할 (0) | 2023.07.06 |
| Typescript를 사용하여 재료 UI 구성 요소의 소품을 확장하는 방법은 무엇입니까? (0) | 2023.07.06 |
| 다른 분기의 커밋된 복사본이 있는 파일의 현재 작업 복사본 (0) | 2023.07.06 |
| newidsql server 함수 내부 (0) | 2023.07.06 |