복붙노트

[SQL] 대신 필터 테이블의 C # 목록을 기반으로 필터 SQL

SQL

대신 필터 테이블의 C # 목록을 기반으로 필터 SQL

나는 다음과 같은 데이터가있는 테이블을 가지고 말 :

지금은 기본 키 부서 및 번호로 필터링 할. 나는 코드를 필터링 할 필요가 부서 및 숫자 조합의 목록을 가지고있다. 내 마음 속에서, 나는이 다음에 그 결과를 조인을 만들 것입니다 :

select * from employee e
inner join dynamicTable dyn on e.Department = dyn.Department 
                           and e.Number = dyn.Number;

dynamicTable 필터에 기본 키가 C # 코드에서 내 목록,하지만 난 데이터베이스 레벨이 목록을 전달하는 방법을 모르겠어요.

내 데이터베이스에 직원의 수백만을 가지고 있기 때문에 나는 나의 직원 테이블에서 모든 및 LINQ 또는 뭔가에 의해 코드에서 해당 필터를로드 할하지 말자.

어디에서 나는 이미 primary_keys 결합에 대해 생각 어디에서를 작성 (...)하지만, 파이어 A의 최대 1500 개 기록에 제한이 있습니다.

사용되는 데이터베이스는 파이어 버드 버전 2.1입니다

해결법

  1. ==============================

    1.개인적으로 난 당신이 추구 할 수있는 두 개의 트릭을 볼 수 있습니다. 그리고 더 하나 "과거의 폭발".

    개인적으로 난 당신이 추구 할 수있는 두 개의 트릭을 볼 수 있습니다. 그리고 더 하나 "과거의 폭발".

    경로 # 1. 사용 GTT : GLOBAL TEMPORARY TABLE

    GTTs는 FB 2.1에 소개 된 (그리고 u는 그것을 사용) 및 연결 별 또는 거래 될 수 있었다. 당신은 트랜잭션 당 하나를 원하는 것입니다. 이 차이는 스키마 (구조와 인덱스, 메타 데이터) 지속적 데이터 (행)에 관한 것입니다. 페이지의이 GTT 문서의 DELETE ROWS 옵션을 COMMIT.

    등등.

    이런 식으로, 당신은 트랜잭션을 열고, 당신은 (서버에 워크 스테이션에서 데이터의 그 1500 값 쌍을 복사) 목록에서 데이터로 GTT을 채우기, 당신은 당신이 COMMIT 후 GTT 것을 통해 가입하여 쿼리를 실행하고 트랜잭션 (transaction) 테이블 내용은 자동 삭제됩니다.

    당신이 세션에서 많은 거의-유사한 쿼리를 실행할 수 있다면, 그것은 의미 당신이 모든 다음 트랜잭션의 모든 다음 쿼리를 재 채우기보다는, 필요에 따라 GTT 당 연결하는 대신 데이터를 수정하는 것을 확인 할 수 있도록 수 하지만 더 복잡한 방법이다. 정화-초마다 COMMIT에 주장까지 당 연결이 특정한 경우에 더 나은 왜 내가 기본 접근 방식으로 원합니다 것입니다. 그냥 쿼리 사이의 서버에 그 쓰레기를 유지하지.

    경로 # 2. 사용 문자열 검색 - LIKE 일치를 반전.

    기본적인 형태이 방법은 정수 번호의 일부 거대하고 임의의 목록을 검색 작동합니다. 귀하의 경우는 조금 더 복잡하다, 당신은 숫자가 아니라 한 사람 쌍에 대해 일치합니다.

    간단한 아이디어가 같다, 이제 우리는 ID의 열은 1, 4, 12, 24이 될 수있는 행을 인출 할 가정하자. 직접적인 접근 방식은 하나의 모든 값에 대해 (4 개)를 검색하도록하거나 제조 될 WHERE ID = 1 ID = 4, ... 또는 WHERE 아이디 IN (1,4,12,24)을 사용. 내부적으로, IN이 그에 언 롤링 할 것이다 매우 = 또는 = 또는 = 다음 대부분의 아마 네 개의 쿼리로 실행. 긴 목록에 매우 효율적으로하지 않습니다.

    그래서 그 대신 - 경기 정말 긴 목록을 위해 - 우리는 특별한 문자열을 형성 할 수있다. 그리고 텍스트로 일치합니다. 이 차종은 훨씬 덜 효율적으로 자신을 일치하고 색인을 사용 금지, 서버는 자연 SCAN은 전체 테이블을 통해 실행 - 그러나 그것은 스캔 한 패스합니다. 일치하는 목록은 정말 큰 경우, 모든 테이블 스캔에 의해 인덱스 페치 수천보다 더 효율적 도착 하나는 패스. 하지만 - 목록 식탁 비율이 정말 큰 경우에만, 특정 데이터에 따라 달라집니다.

    우리는 우리의 목표 값에 의해 산재 및 구분에 랩을 입대 텍스트합니다 "~ 1 ~ 4 ~ 12 ~ 24 ~". 이제 우리는 우리의 ID 열 같은 구분 번호 구분자 문자열을 만들고 이러한 하위 문자열을 찾을 수 있는지 여부를 참조하십시오.

    SELECT *를 WHERE COLUMN_NAME으로 함유하는 VALUE_PARAM the_table에서 : LIKE의 일반적인 사용은 / 함유 아래와 같이 데이터에 대해 열을 일치하는 것입니다 우리는 the_table에서 *는, SELECT 역 WHERE column_name에 기반 표현을 포함 VALUE_PARAM

      SELECT * from the_table WHERE '~1~4~12~24~' CONTAINING '~' || ID || '~' 
    

    이 ID는 자동 캐스트 문자열로 정수에서 얻을 것이다 가정합니다. 그렇지 않은 경우 수동으로해야 할 것 : .... ( '')가 포함 된 ~ '|| CAST (VARCHAR 같은 ID (100)) || '~'

    귀하의 경우는 조금 더 복잡하다, 당신은 당신이이 방법을 따르는 경우, 두 개의 서로 다른 구분 기호를 사용하는 것, 그래서 두 개의 숫자, 부서 및 번호와 일치해야합니다. 같은 뭔가

    SELECT * FROM employee e WHERE
      '~1@10~1@11~2@20~3@7~3@66~' CONTAINING
      '~' || e.Department || '@' || e.Number || '~'
    

    잡았다 : 당신은 당신의 대상 목록 1500 개 요소를 말한다. 목표 라인은 긴 ... 것이다. 정확히 어떻게 긴 ???

    파이어에서 VARCHAR는 32킬로바이트 AFAIR로 제한되고, 긴 텍스트는 제한된 기능, 텍스트에 BLOB로해야한다. FB2.1에서 BLOB를 상대로하는 것처럼 사용할 수 있습니까? 나는 기억 릴리스 노트를 확인하지 않습니다. 라이브러리도 당신이 BLOB하지 문자열로 매개 변수 유형을 지정할 수 있습니다 것인지도 확인한다. 지금, 당신의 연결의 CHARSET은 무엇인가? 이 윈도우 1250 또는 윈도우 1251과 같은 것입니다 경우 - 다음 한 문자는 1 바이트, 당신은 32 kbytes에 32K 캐릭터에 맞게 할 수 있습니다. 그러나 연결 CHARSET 응용 프로그램 세트의 경우 UTF-8 - 다음 각 문자는 4 바이트 소요되며 최대 VARCHARable 문자열은 8K 문자로 감소됩니다.

    이 긴 문자열 매개 변수를 사용하지 않도록하고, SQL 문에 대상 문자열 상수를 인라인 시도 할 수 있습니다. 그러나 대신 최대 SQL 문 길이의 한도에 도달 할 수 있습니다.

    참조 : 월 $ CHARACTER_SET_ID는 C에서 : \ 프로그램 파일 \ 파이어 버드 \ Firebird_2_1 아이디로 캐릭터 세트 텍스트 이름을 맵핑하는 방법을 FB의 문서에서 \ 문서 \ README.monitoring_tables.txt 다음 시스템 테이블 섹션을.

    경로 # 3 가난한 사람의 GTT. 의사 테이블을 입력합니다.

    GTTs가 도입되기 전에이 트릭은 오래된 IB / FB 버전에서 종종 사용될 수 있습니다.

    프로 : 당신이 당신의 지속적인 스키마를 변경할 필요가 없습니다. 단점 : 계획을 변경하지 않고 - 당신이 인덱스를 만들 수 없습니다와 결합 색인을 사용할 수 없습니다. 그리고 다시 한번, 당신은 하나의 SQL 문장의 길이 제한을 칠 수있다.

    정말,이 그냥 대답은 내가이 트릭은 너무 언급해야한다고 생각 완료하기 위해, 귀하의 경우에 적용 할 수있을 거라고 생각하지 않습니다.

    select * from employee e, (
      SELECT 1 as Department, 10 as Number FROM RDB$DATABASE
      UNION ALL SELECT 1, 11 FROM RDB$DATABASE
      UNION ALL SELECT 2, 20 FROM RDB$DATABASE
      UNION ALL SELECT 3, 7 FROM RDB$DATABASE
      UNION ALL SELECT 3, 66 FROM RDB$DATABASE
    ) t, 
    where e.Department = t.Department 
      and e.Number = t.Number
    

    원유 및 추악한,하지만 때로는이 의사 테이블 힘 도움이됩니다. 언제? 대부분은 수 있도록하는 데 도움이 배치 인덱싱 D는 필요 그것은 SELECT들에 거의 적용되지 않으며, INSERT --SELECT에서 - 그러나 단지 트릭을 알고있다.

  2. from https://stackoverflow.com/questions/43997516/filter-sql-based-on-c-sharp-list-instead-of-a-filter-table by cc-by-sa and MIT license