2013-04-19 5 views
1

Я пытаюсь написать sql с предложением where, которое проверяет, есть ли какой-либо элемент в списке в другом списке. Есть ли более короткий способ сделать это, а не проверять каждого члена первого списка?Найти список значений в списке значений

SELECT * from FOO 
WHERE FOO.A IN ('2','3', '5', '7','11','13','17','19') OR 
    FOO.B IN ('2','3', '5', '7','11','13','17','19') OR 
    FOO.C IN ('2','3', '5', '7','11','13','17','19') OR 
    FOO.D IN ('2','3', '5', '7','11','13','17','19') OR 
    FOO.E IN ('2','3', '5', '7','11','13','17','19') OR 
    FOO.F IN ('2','3', '5', '7','11','13','17','19') 

Это упрощенная sql.

пытается не мутить воду слишком много, но так как вы спросите:

В конце концов, что я пытаюсь сделать здесь, выберите строки из FOO, что имеет столбцы удовлетворения различных критериев. Эти критерии хранятся во второй таблице (назовите ее BAR), в основном db, имя, тип должны совпадать, а флаг должен быть равен 1. Планировал ли построить список IN из BAR, сравнивая их с именами столбцов в INFORMATION_SCHEMA.COLUMNS, содержащих FOO

FOO:

+--------+--------+---------+---------+--------+-------+ 
| DB | Name | Type | Col1 | Col2 | Col3 | 
+--------+--------+---------+---------+--------+-------+ 
| 4 | AC1 | LO  | 1  | 10 | 2  | 
| 4 | AC1 | HI  | 2  | 20 | 4  | 
| 1 | DC2 | HI-HI | 11  | 5  | 2  | 
| 1 | DC2 | HI  | 22  | 10 | 4  | 
| 1 | DC2 | LO  | 33  | 15 | 6  | 
+--------+--------+---------+---------+--------+-------+ 

BAR:

+--------+--------+---------+---------+--------+ 
| DB | Name | Type | Field | Flag | 
+--------+--------+---------+---------+--------+ 
| 4 | AC1 | LO  | Col1 | 1  | 
| 4 | AC1 | HI  | Col1 | 1  | 
| 1 | DC2 | HI-HI | Col1 | 1  | 
| 1 | DC2 | HI  | Col1 | 1  | 
| 1 | DC2 | LO  | Col1 | 1  | 
| 4 | AC1 | LO  | Col2 | 0  | 
| 4 | AC1 | HI  | Col2 | 0  | 
| 1 | DC2 | LO  | Col2 | 0  | 
| 1 | DC2 | HI-HI | Col2 | 0  | 
| 1 | DC2 | HI  | Col2 | 0  | 
| 4 | AC1 | LO  | Col3 | 0  | 
| 4 | AC1 | HI  | Col3 | 0  | 
| 1 | DC2 | LO  | Col3 | 0  | 
| 1 | DC2 | HI-HI | Col3 | 0  | 
| 1 | DC2 | HI  | Col3 | 0  | 
+--------+--------+---------+---------+--------+ 
+0

Какой диалект SQL вы используете? Если это то, где вы можете определить переменные, тогда это должно быть выполнимо. Во всяком случае, что такое диалект? –

+0

В настоящее время я пытаюсь заставить это работать с ms sql – aggaton

+0

Можете ли вы опубликовать структуру таблицы для 'Foo'? Вам нужны другие столбцы в таблице? – Taryn

ответ

0

Ваш метод, вероятно, работает лучше всего. Вот альтернатива, которая требует только создания списка один раз. Он использует КТР, чтобы создать список значений, а затем в положение exists, чтобы проверить, соответствует ли какому-либо значение:

with vals as (
     select '2' as p union all 
     select '3' union all 
     select '5' union all 
     select '7' union all 
     select '11' union all 
     select '13' union all 
     select '17' union all 
     select '19' 
    ) 
select * 
from foo 
where exists (select 1 from vals where vals.p in (foo.A, foo.B, foo.C, foo.D, foo.E, foo.F)) 

Если вы используете базу данных, которая не поддерживает КТР, вы можете просто поместить код where пункт:

select 8 
from foo 
where exists (select 1 
       from (select '2' as p union all 
        select '3' union all 
        select '5' union all 
        select '7' union all 
        select '11' union all 
        select '13' union all 
        select '17' union all 
        select '19' 
        ) t 
       where vals.p in (foo.A, foo.B, foo.C, foo.D, foo.E, foo.F) 
      ) 

Если вы используете Oracle, то вам нужно добавить from dual в формулировках после строки констант. В противном случае, я думаю, что один или другой должен работать в любой базе данных SQL.

+0

Что делать, если OP использует 'mysql'? – Kermit

+0

@FreshPrinceOfSO. , , Если OP не указывает базу данных, я думаю, что ANSI SQL отлично подходит для решения. В любом случае я добавил эквивалентный оператор в MySQL. –

0

При первом осмотре кажется, что ваша схема не подходит для типа запроса, который вы выполняете. Похоже, что вы хотели бы таблицу FOOVAL с типом и значением, то вы просто запрос становится:

CREATE TABLE FOOVAL 
{ 
    ID int, -- References FOO.ID 
    TYPE char, -- A, B, C, D, E, F 
    VAL int 
} 

SELECT * FROM FOO WHERE FOO.ID IN 
(SELECT DISTINCT FOOVAL.ID WHERE FOOVAL.VAL IN ('2','3', '5', '7','11','13','17','19')) 
0

Хотя это не совсем понятно, что вы хотите делать с данными, так как вы используете SQL Сервер мое предложение было бы использовать функцию UNPIVOT превратить col1, col2 и col3 столбцов в строки, которые облегчат фильтровать данные:

select db, name, type, col, value 
from foo 
unpivot 
(
    value 
    for col in (Col1, Col2, Col3) 
) unpiv; 

SQL Fiddle with Demo См. Это дает данные в следующем формате:

| DB | NAME | TYPE | COL | VALUE | 
------------------------------------ 
| 4 | AC1 | LO | Col1 |  1 | 
| 4 | AC1 | LO | Col2 | 10 | 
| 4 | AC1 | LO | Col3 |  2 | 
| 4 | AC1 | HI | Col1 |  2 | 

После того, как в формате строки, она должна быть значительно проще применять любые фильтры или даже присоединиться к вашему BAR столу.

Смежные вопросы