2014-01-24 3 views
0

Я смотрю на 5 разных столбцов (db сделал плохо, к сожалению). Если из пяти столбцов два имеют одно значение «1» и одно значение «2», я хочу, чтобы эта запись была исключена из результатов. Однако, если у него есть только одно из двух значений, я хочу, чтобы оно было включено.Использование Boolean для определения 5-way Где статья

У меня есть это до сих пор, но я уверен, что он не включит запись, если у нее есть хотя бы одно из двух значений.

NOT ((Ew.DocRecvd1 = 10 OR Ew.DocRecvd1 = 11) OR 
(Ew.DocRecvd2 = 10 OR Ew.DocRecvd2 = 11) OR 
(Ew.DocRecvd3 = 10 OR Ew.DocRecvd3 = 11) OR 
(Ew.DocRecvd4 = 10 OR Ew.DocRecvd4 = 11) OR 
(Ew.DocRecvd5 = 10 OR Ew.DocRecvd5 = 11)) 

Спасибо.

+0

Какую базу вы используете? –

+0

Что вы пытаетесь сделать, не совсем понятно, можете ли вы показать нам некоторые примеры данных, сообщающих нам, что следует и не следует включать? – Eluvatar

+0

Ваш текст говорит о '1' и' 2', но ваш код использует '10' и' 11'. Что вы хотите использовать? – FrankPl

ответ

1

Я предлагаю вам подсчитать количество значений в каждой группе, которую вы хотите. И я бы сделал это в подзапросе, просто потому, что это делает код более читабельным и поддерживаемым.

Вот пример:

from (select t.*, 
      ((case when Ew.DocRecvd1 in (10, 11) then 1 else 0) + 
       (case when Ew.DocRecvd2 in (10, 11) then 1 else 0) + 
       (case when Ew.DocRecvd3 in (10, 11) then 1 else 0) + 
       (case when Ew.DocRecvd4 in (10, 11) then 1 else 0) + 
       (case when Ew.DocRecvd5 in (10, 11) then 1 else 0) + 
      ) as Num1s, 
      <something similar> as Num2s 
     from table t 
    ) t 
where Num1s = 2 and Num2s = 1; 
+0

Я думаю, что понимаю это !!! Итак, если бы я хотел исключить любые записи с BOTH 10 и 11 в два из пяти, я бы сделал NOT num1s = 2 Справа? – CRBN

+0

@ пользователь3191081. , , Я думаю так. Это исключает любую строку, в которой два столбца содержат либо '10', либо' 11'. –

+0

Хорошо, я сейчас работаю над этим, очень ценю. – CRBN

1

Вы утверждаете условия фильтра просто в пункте where. Учитывая таблицу

create table foobar 
(
    id int not null primary key , 
    c1 int not null , 
    c2 int not null , 
    c3 int not null , 
    c4 int not null , 
    c5 int not null , 
) 
go 

Вы можете сказать

select * 
from foobar 
where not ( 2 = case c1 when 1 then 1 else 0 end 
        + case c2 when 1 then 1 else 0 end 
        + case c3 when 1 then 1 else 0 end 
        + case c4 when 1 then 1 else 0 end 
        + case c5 when 1 then 1 else 0 end 
      and 1 = case c1 when 2 then 1 else 0 end 
        + case c2 when 2 then 1 else 0 end 
        + case c3 when 2 then 1 else 0 end 
        + case c4 when 2 then 1 else 0 end 
        + case c5 when 2 then 1 else 0 end 
     ) 

Другой подход, который может работать быстрее, чтобы использовать в качестве маски таблицы, содержащий условия, которые необходимо исключить. Что-то вроде этого:

create table mask 
(
    c1 tinyint null , 
    c2 tinyint null , 
    c3 tinyint null , 
    c4 tinyint null , 
    c5 tinyint null , 
    unique clustered (c1,c2,c3,c4,c5) , 
) 

В вашем случае, должны быть исключены только 30 Условия:

c1 c2 c3 c4 c5 
---- ---- ---- ---- ---- 
NULL NULL 1 1 2 
NULL NULL 1 2 1 
NULL NULL 2 1 1 
NULL 1 NULL 1 2 
NULL 1 NULL 2 1 
NULL 1 1 NULL 2 
NULL 1 1 2 NULL 
NULL 1 2 NULL 1 
NULL 1 2 1 NULL 
NULL 2 NULL 1 1 
NULL 2 1 NULL 1 
NULL 2 1 1 NULL 
1 NULL NULL 1 2 
1 NULL NULL 2 1 
1 NULL 1 NULL 2 
1 NULL 1 2 NULL 
1 NULL 2 NULL 1 
1 NULL 2 1 NULL 
1 1 NULL NULL 2 
1 1 NULL 2 NULL 
1 1 2 NULL NULL 
1 2 NULL NULL 1 
1 2 NULL 1 NULL 
1 2 1 NULL NULL 
2 NULL NULL 1 1 
2 NULL 1 NULL 1 
2 NULL 1 1 NULL 
2 1 NULL NULL 1 
2 1 NULL 1 NULL 
2 1 1 NULL NULL 

(30 row(s) affected) 

Фактический запрос тривиальна тогда (и если у вас есть покрывающий индекс на колонки для тестирования, тест проводится с индексом ищет и поэтому должны выполнять очень хорошо:

select * 
from dbo.foobar t 
where not exists (select * 
        from mask m 
        where t.c1 = m.c1 
        and t.c2 = m.c2 
        and t.c3 = m.c3 
        and t.c4 = m.c4 
        and t.c5 = m.c6 
       ) 

преимущество этого подхода состоит в том, что правила et is table-driven, что означает, что будущие изменения правил - это просто модификации данных в вашей таблице масок.

Вы также можете использовать положительный набор правил, но в вашем случае набор больше (> 200 положительных случаев, в отличие от 30 отрицательных случаев).

0

ОК, я думаю, что нашел результат, которого я хотел.

Я использовал следующий в предложении WHERE моего запроса:

NOT 
    (2 = 
    (CASE WHEN Ew.DocRecvd1 = 10 THEN 1 ELSE 0 END 
     + 
    CASE WHEN Ew.DocRecvd2 = 10 THEN 1 ELSE 0 END 
     + 
    CASE WHEN Ew.DocRecvd3 = 10 THEN 1 ELSE 0 END 
     + 
    CASE WHEN Ew.DocRecvd4 = 10 THEN 1 ELSE 0 END 
     + 
    CASE WHEN Ew.DocRecvd5 = 10 THEN 1 ELSE 0 END 
     + 
    CASE WHEN Ew.DocRecvd1 = 11 THEN 1 ELSE 0 END 
     + 
    CASE WHEN Ew.DocRecvd2 = 11 THEN 1 ELSE 0 END 
     + 
    CASE WHEN Ew.DocRecvd3 = 11 THEN 1 ELSE 0 END 
     + 
    CASE WHEN Ew.DocRecvd4 = 11 THEN 1 ELSE 0 END 
     + 
    CASE WHEN Ew.DocRecvd5 = 11 THEN 1 ELSE 0 END)) 

Это возможно только в моей БД, чтобы получить эти два документа в одном из пяти мест в пределах одной записи, так что счетчик не может идти более двух с двумя документами, которые я ищу.

Престижность Николасу Кэри и Гордону Линоффу за то, что он вложил меня в то, что я мог сделать и искать!

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