2016-04-06 6 views
0

Я пытаюсь вернуть идентификаторы DISTINCT из таблицы, если она соответствует определенным критериям.Возвращает отдельный идентификатор, основанный на нескольких критериях

  1. Идентификатор должен содержать ИДС 1,26,33,49 (все)
  2. Идентификатор не должен содержать ИДС 38 или 46 или 67

Вот таблица ,

enter image description here

Вот что я до сих пор:

SELECT DISTINCT(c1.id) FROM cte c1 
LEFT JOIN cte c2 
ON c1.id = c2.ID 
AND c2.CID = 38 
where c2.id IS null 

Это работает только если указать один идентификатор, который не должен быть представлен. Если я заменю этот

AND c2.CID = 38 

с

AND c2.CID IN (38,46,67) 

Это не вернет мне правильный идентификатор. Кроме того, если я добавлю критерии для c1.CID, чтобы включить идентификаторы 1,26,33,49 Он также вернет неверный идентификатор.

Основываясь на этой таблице примеров, я должен только вернуться ID 12345.

Вот SQLFIDDLE.

Я пытаюсь получить этот вывод без использования subquery.

Любые предложения?

+0

Я не понимаю, почему этот запрос не работает: «выберите отдельный идентификатор из вашей таблицы, где CID в (1,26,33,49)» – FLICKER

+0

Это не сработает. «ID» может иметь несколько строк с разными «CID». Если я просто сделаю один выбор, то он исключит только строку, но это не исключает идентификатор. – smr5

+0

критерии @burzum 'множественное число, единственное значение - это критерий, поэтому «критерий» - это не слово. –

ответ

3

SQL Fiddle

Использование условной агрегации.

SELECT id 
FROM cte 
group by id 
having sum(case when cid in (1,26,33,49) then 1 else 0 end) = 4 
and sum(case when cid in (38,46,67) then -1 else 0 end) = 0 
+0

Спасибо. Ваше решение работает для меня. Не могли бы вы объяснить, что здесь делает 'sum'. Я понимаю, что случай, и '4' представляет все идентификаторы, должен присутствовать, но я не понимаю цели' sum'. – smr5

+0

вы назначаете 1 строкам, содержащим эти значения, и суммируете их для каждого идентификатора и проверяете, равно ли оно 4. Для исключения cid следует сделать то же самое, но назначить -1 строкам, которые имеют эти 3 cid, а затем сделать сумму. Если какой-либо из этих cid присутствует для данного идентификатора, тогда сумма не будет равна 0 и условие не будет выполнено, и эти идентификаторы не будут возвращены. –

+0

Awesome. Спасибо за объяснение. – smr5

0

Почему вы не сделали ничего подобного?

AND c2.CID = 38 OR c2.CID = 46 OR c2.CID = 67 

или

AND c2.CID Like (38,46,67) 
1

Я создал рабочий запрос, но выглядит очень странно :)

-- An ID must contain CID of 1,26,33,49 (all) 
-- An ID should NOT contain CID of 38 or 46 or 67 
SELECT valid.ID 
FROM (
    SELECT ID, CID 
    FROM CTE 
    WHERE CID IN (1,26,33,49) 
    GROUP BY ID, CID 
) AS valid 
WHERE valid.ID NOT IN (
    SELECT ID FROM CTE WHERE CID IN (38,46,67) GROUP BY ID, CID 
) 
GROUP BY valid.ID 
HAVING COUNT(valid.CID) = 4 

Работа sqlfiddle: http://sqlfiddle.com/#!6/9c862/41

P.S. «4» - это число обязательных идентификаторов. если вы измените количество параметров - должно быть соответствующим образом обновлено предложение HAVING COUNT.

+0

@pavel_morshenyuk Я предлагаю отредактировать как: HUNING COUNT (DISTINCT valid.CID) = 4 Вам нужно учесть возможные множественные записи для данного CID. –

+0

@ ricardo-c спасибо за предложение! Вероятно, это имеет смысл –

1

ЗА ИСКЛЮЧЕНИЕМ ПРОТИВ СОЮЗА в манере говорить.

SELECT c1.id 
FROM cte c1 
WHERE c1.CID IN(1,26,33,49) 
GROUP BY c1.id 
HAVING COUNT(DISTINCT c1.CID) = 4 

EXCEPT 

SELECT DISTINCT c1.id 
FROM cte c1 
WHERE c1.CID IN(38,46,67) 
+0

Другие примеры не учитывают повторяющиеся записи, например. четыре дублированные записи с ID 12345 и CID 26 –

+0

Странно. Он работает в SQLFIDDLE, но когда я запускаю тот же запрос к моей таблице, я не получаю никаких результатов. – smr5

+0

@burzum umm может быть, ваш стол другой, попробуйте скопировать из sqlfiddle обе части; «построить схему» и «запустить sql» и проверить, что в вашей SSMS. –

1

Если вы готовы использовать временную таблицу, это работает.А вот SQL Скрипки: http://sqlfiddle.com/#!6/9c862/39/0

Select 
    C.ID 
,C.CID 
,Case C.CID 
    When 1 then 'Y' 
    When 26 then 'Y' 
    When 33 then 'Y' 
    When 49 then 'Y' 
    Else 'N' 
    End as "Keep" 
,Case C.CID 
    When 38 then 'Y' 
    When 46 then 'Y' 
    When 67 then 'Y' 
    Else 'N' 
    End as "Remove" 

Into #Temp 

From CTE as C 



Select Distinct 
    T.ID 

From #Temp as T 

Group by T.ID 

Having 
    Sum(Case When T.Keep = 'Y' Then 1 Else 0 End) = 4 
    and 
    Sum(Case When T.Remove = 'Y' then 1 Else 0 End) = 0 

Сначала я не принял во внимание, если та же идея была кратной же CID даже вариант. Если это так, вы должны иметь возможность добавить отдельный отчет для первого оператора выбора, чтобы сделать это по-прежнему работать.

+0

Плюс '1' за усилия! – smr5

+0

dang та же концепция, но без таблицы temp @vkp хорошо там, я не думал об использовании предложения о наличии до тех пор, пока я не получил временную таблицу. закрыть хотя –

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