Поиск значений в предложении "IN", которые не соответствуют записи

У меня есть таблица dept с записями eng и finance. Он не содержит записей для foo, bar или baz. У меня есть запрос на спящий режим, который возвращает записи, соответствующие тому, что я ищу. Это выглядит так:

select * from dept where dept.name in (eng, foo, bar, baz, finance);

Запрос работает нормально и делает то, что мне нужно для этого (находит eng и finance). Однако мне также нужно распечатать сообщение журнала для тех, которые не соответствуют записи (foo, bar и baz):

log.debug ("could not find records where dept.name in foo, bar, baz");

Есть ли простой способ сделать это в спящем режиме?

Из того, что я вижу, единственным решением является создание некоторой структуры со всеми гипотетическими значениями и удаление вещей, найденных в запросе.

5 ответов

Как указано a_horse_with_no_name, вы не указали свою СУБД. Это решение SQL Server 2008:

select input.name
from (values
 ('eng'),
 ('foo'),
 ('bar'),
 ('baz'),
 ('finance')
)[input](name)
left join depts d on d.name = input.name
where d.name is null


Вы не указали свои СУБД, так что это ANSI SQL:

with names (dname) as (
 values 
 ('eng'), 
 ('foo'),
 ('bar'),
 ('baz'),
 ('finance')
)
select n.dname 
from names as n
 left join depts as d on d.name = n.dname
where d.name is null;


Честно говоря, могут быть какие-то грязные трюки, которые заставляют его выглядеть так, как будто он работал непосредственно в запросе, но зачем делать запрос недостижимым и помещать ненужную бизнес-логику в уровень доступа к данным? Это очень просто сделать в коде.

В псевдокоде это просто что-то вроде:

List<department> searchByDeptNames(List<string> deptNames) {
 List<department> depts = 
 session.createQuery("from dept where dept.name in (:deptNames)")
 .setParameter("deptNames", deptNames)
 .list();
 // log down unmatched dept names
 if (logger.isDebugEnabled()) {
 Set<string> unmatchedDeptNames = new HashSet<string>(deptNames);
 for (Department dept : depts) {
 *************************.remove(dept.getName());
 }
 logger.debug("no record found for dept names : " + unmatchedDeptNames );
 }
 return depts;
}
</string></string></department></string></department>

Запрос будет даже более грязным, если вы намерены передать значения предложения in во время выполнения.


Вы можете просто CONCAT имена полей, и в результате список будет иметь то, что вы хотите напечатать как ошибку:

select 
 dept.name as name, 
 CONCAT(
 case 
 when !eng
 then 'eng, '
 else ''
 end,
 case 
 when !foo
 then 'foo, '
 else ''
 end,
 case 
 when !bar
 then 'bar, '
 else ''
 end,
 case 
 when !baz
 then 'baz, '
 else ''
 end,
 case 
 when !finance
 then 'finance'
 else ''
 end) as errorFields
from dept where dept.name not in (eng, foo, bar, baz, finance)

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


Select * from dept where dept.name not in (eng, foo, bar, baz, finance)

licensed under cc by-sa 3.0 with attribution.