2013-02-15 1 views
2

У меня есть таблица, определенные и заселенных следующим образом:Sql: Выберите, где условие истинно для всех типов

DECLARE @Temp TABLE 
(
    ProjectId INT, 
    EmployeeId INT, 
    SomeTypeId INT, 
    IsExpired BIT, 
    IsWarning BIT, 
    IsIncomplete BIT 
) 

--all incomplete... 
INSERT INTO @Temp VALUES (1, 1, 1, 0, 0, 1) 
INSERT INTO @Temp VALUES (1, 1, 2, 0, 0, 1) 
INSERT INTO @Temp VALUES (1, 1, 3, 0, 0, 1) 

--two warnings... 
INSERT INTO @Temp VALUES (1, 2, 1, 0, 1, 0) 
INSERT INTO @Temp VALUES (1, 2, 2, 0, 1, 0) 
INSERT INTO @Temp VALUES (1, 2, 3, 0, 0, 0) 

--two expirations... 
INSERT INTO @Temp VALUES (1, 3, 1, 0, 0, 0) 
INSERT INTO @Temp VALUES (1, 3, 2, 1, 0, 0) 
INSERT INTO @Temp VALUES (1, 3, 3, 1, 0, 0) 

Я хочу вернуться отчетливое ProjectID, EmployeeID пары с любыми предупреждениями или выдохов:

SELECT DISTINCT ProjectId, EmployeeId FROM @Temp WHERE IsWarning = 1 OR IsExpired = 1 

Нет проблем.

Однако, я хотел бы также возвращать пары ProjectId, EmployeeId, где IsWarning = 0 и IsExpired = 0 и IsIncomplete = 1, но это должно быть верно для всех SomeTypeId (1, 2, 3). Другими словами, никаких предупреждений, без истечения срока действия, просто неполных для всех категорий.

SomeTypeId Fks для таблицы поиска. Сейчас есть только 3 записи, но в будущем их может быть больше.

Любые идеи?

Ожидается, что ProjectId, EmployeeId (1, 1) будет возвращен.

ответ

2

Этот использует MAX и MIN, чтобы увидеть, что все значения одинаковы; нужно добавить + 0 к каждому биту, чтобы сделать его доступным для обычных числовых агрегатных функций (например, MIN/MAX/SUM/...)

SELECT ProjectId, EmployeeId 
FROM Temp 
GROUP BY ProjectId, EmployeeId 
HAVING MAX(IsWarning + 0) = 0 
    AND MAX(IsExpired + 0) = 0 
    AND MIN(IsIncomplete + 0) = 1 

An SQLfiddle for testing.

+0

Это не работает для сценария, где 'все 1,2,3 SomeTypeId' записи имеют' IsWarning = 0 и IsExpired = 0 и IsIncomplete = 1' – Kaf

+0

@Kaf Hm? Возможно, я очень неправильно понял вопрос, но я не вижу, какой случай не сработает. Не могли бы вы привести встречный пример? –

+0

Хорошее решение. Спасибо. –

0

Я не уверен в вашем вопросе, если вы имеете в виду, что хотите получить эти результаты в ТОЧНОМ запросе или хотите получить совершенно новый запрос. Предполагая, что последний, ваш запрос будет:

SELECT DISTINCT ProjectId, EmployeeId FROM @Temp WHERE (IsWarning = 0 AND IsExpired = 0 AND IsIncomplete = 1) 

Предполагая, что первое, было бы:

SELECT DISTINCT ProjectId, EmployeeId FROM @Temp WHERE (IsWarning = 1 OR IsExpired = 1) 

ИЛИ (IsWarning = 0 И IsExpired = 0 и IsIncomplete = 1)

+0

Ну ... Не совсем. Для неполного случая мне нужно убедиться, что ваш первый запрос верен, но по всем типам, определенным SomeTypeId. –

0

Попробуйте это, если у вас нет дубликатов записей;

Пожалуйста, обратите внимание, что union добавляется предполагая вам еще нужно, чтобы выбрать данные WHERE IsWarning = 1 OR IsExpired = 1. Если вам не нужны, просто удалите его.

SQL-DEMO HERE

;with cte as (
    select projectid, employeeid, 
     case when sometypeid in (1,2,3) and 
        IsWarning = 0 and IsExpired = 0 and IsIncomplete = 1 
       then 1 else 0 end x 
    from temp 
) 
select projectid, employeeid 
from cte 
group by projectId, employeeid 
having sum(x) >= 3 
union 
select projectid, employeeid 
from Temp 
where IsWarning = 1 or IsExpired = 1 
Смежные вопросы