簡體   English   中英

使用復合鍵的WHERE_IN查詢?

[英]WHERE_IN query with a composite key?

假設我有一個包含兩部分組成的組合鍵和4條記錄的表,如下所示:

KEY_PART_1 KEY_PART_2
A          1
B          1
C          2
C          3

我想編寫一些動態SQL,以使用“ WHERE IN”子句僅選擇記錄B,1和C,2, 而不選擇A,1或C,3。

沒有臨時表,有什么方法可以做到這一點嗎?

沒關系,但是我們目前正在使用Oracle,並希望盡快遷移到PostgreSQL。

此語法適用於Oracle和PostgreSQL:

SELECT *
  FROM table_name
 WHERE (key_part_1, key_part_2) IN ( ('B',1), ('C',2) );

在@Justin Cave的回答之后,這是一個小測試用例,用於說明Oracle將對以下過濾謂詞執行INDEX RANGE SCAN,然后執行INLIST ITERATOR

WHERE (key_part_1, key_part_2) IN ( ('B',1), ('C',2) )

設定

SQL> CREATE TABLE t(key1 VARCHAR2(1), key2 NUMBER);

Table created.

SQL>
SQL> INSERT INTO t VALUES('A', 1);

1 row created.

SQL> INSERT INTO t VALUES('B', 1);

1 row created.

SQL> INSERT INTO t VALUES('C', 2);

1 row created.

SQL> INSERT INTO t VALUES('C', 3);

1 row created.

SQL>
SQL> COMMIT;

Commit complete.

SQL>

key1和key2的 復合索引

SQL> CREATE INDEX t_idx ON t(key1, key2);

Index created.

SQL>

收集統計信息:

SQL> EXEC DBMS_STATS.gather_table_stats('LALIT', 'T');

PL/SQL procedure successfully completed.

SQL>

執行查詢:

SQL> SELECT * FROM t
  2  WHERE (key1, key2) IN ( ('B',1), ('C',2) );

K       KEY2
- ----------
B          1
C          2

SQL>

因此,它給出了正確的輸出。

讓我們看一下解釋計划

案例#1鍵值對的索引順序相同。 領先的關鍵。

SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2301620486

---------------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |     2 |    10 |     1   (0)| 00:00:01 |
|   1 |  INLIST ITERATOR  |       |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| T_IDX |     2 |    10 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------

   2 - access(("KEY1"='B' AND "KEY2"=1 OR "KEY1"='C' AND "KEY2"=2))

14 rows selected.

案例#2索引相反的鍵值對。 前導鍵反向。

SQL> EXPLAIN PLAN FOR SELECT * FROM t
  2  WHERE (key2, key1) IN ( (1, 'B'), (2, 'C') );

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2301620486

---------------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |     2 |    10 |     1   (0)| 00:00:01 |
|   1 |  INLIST ITERATOR  |       |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| T_IDX |     2 |    10 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------

   2 - access(("KEY1"='B' AND "KEY2"=1 OR "KEY1"='C' AND "KEY2"=2))

14 rows selected.

在這兩種情況下, Oracle都使用index

我不確定,但我認為您想要這樣的東西,幾乎適用於所有RDBMS:

select KEY_PART_1, KEY_PART_2 from your_table where KEY_PART_1='B' and KEY_PART_2 = '1'
UNION
select KEY_PART_1, KEY_PART_2 from your_table where KEY_PART_1='C' and KEY_PART_2 = '2'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM