У меня есть чувство, когда я вижу решение, я бью себя по лбу, но сейчас я его не вижу.
У меня есть справочная таблица, скажем TableB
, которая выглядит следующим образом. Все поля INT
, кроме двух последних, которые являются BOOL.
ID, TableA_ID, Value, Required, Disqualifies
У меня есть список TableA_Id
значений (1, 2, 3 )
и т. Д.
Для каждой записи в этой таблице либо Обязательное может быть истинным, либо дисквалификация может быть истинной - обе они не могут быть истинными одновременно. Они оба могут быть ложными или нулевыми. Могут быть повторяющиеся значения TableA_Id
, но никогда не должно быть дубликатов TableA_Id
и Value
Если значение true для любого из этих значений TableA_ID, и ни одно из этих значений не находится в моем списке, не возвращает записей. Если ни одно из значений не помечено как обязательное (required = 0 or null)
, то возвращаются записи UNLESS , любое из значений помечается как дисквалифицирующее и находится в списке, и в этом случае я хочу вернуть никаких записей.
Итак, если поле является обязательным и у меня его нет, не возвращайте никаких записей. Если поле помечено как дисквалифицированное и у меня есть, не возвращайте никаких записей. Возвращать запись можно только в том случае, если у меня есть обязательное значение или у меня нет дисквалифицированного значения или нет обязательных значений.
Надеюсь, я все объяснил ясно.
Заранее спасибо за указание в правильном направлении.
В качестве примера того, как могут выглядеть мои записи:
ID TableA_ID Value Required Disqualifies
-- --------- ----- -------- ------------
1 123 1 True False
2 123 2 True False
3 123 3 False False
4 123 4 False True
5 456 1 False True
6 456 2 False False
Учитывая этот набор примеров данных, если мы работаем с TableA_Id
123 и мой список значений, скажем, 1 и 3, я получу возвращенные данные, потому что у меня есть обязательное значение и нет никаких дисквалифицированных значений. Если бы мой список значений был только 3, я не получил бы никаких записей, так как я пропускаю Обязательные значения. Если бы мой список значений был 1 и 4, я бы не получил записей, потому что 4 помечен как дисквалифицированный.
Теперь, если мы работаем с TableA_Id
456, единственный список значений, который будет возвращать любые записи, равен 2.
Может быть, мне следует опубликовать весь SQL-запрос - я старался сделать его таким коротким, чтобы всем было легче, но похоже, что это не так хорошо работает.
Вот полный динамически сгенерированный запрос. Сейчас я работаю над второй строкой снизу. Чтобы сравнить это с моим примером, t.id
будет TableA_ID
, Value
будет PDT_ID
.
SELECT DISTINCT t.ID, t.BriefTitle, stat.Status, lstat.Status AS LocationStatus, st.SType, t.LAgency, l.City, state.StateCode
,( SELECT TOP 1 UserID
FROM TRecruiter
WHERE TrialID = t.ID AND Lead = 1 ), l.ID as LocationID
, l.WebBased
FROM Trial t
INNER JOIN Location l ON t.ID = l.TrialID
FULL JOIN pdt on t.ID = pdt.trialid
FULL JOIN pdm on t.ID = pdm.TrialID
FULL JOIN s on t.ID = s.TrialID
FULL JOIN hy on t.ID = hy.TrialID
FULL JOIN ta on t.ID = ta.TrialID
FULL JOIN stt on t.ID = stt.TrialID
FULL JOIN [Status] stat ON t.StatusID = stat.ID
FULL JOIN st ON t.StudyTypeID = st.ID
FULL JOIN State state ON l.StateID = state.ID
FULL JOIN [Status] lstat ON l.StatusID = lstat.ID
FULL JOIN ts ON t.ID = ts.TrialID
FULL JOIN tpdm ON t.ID = tpdm.TrialID
WHERE ((t.ID IS NOT NULL)
AND (EligibleHealthyVolunteers IS NULL OR EligibleHealthyVolunteers = 1 OR (0 = 0 AND EligibleHealthyVolunteers = 0))
AND (eligiblegenderid is null OR eligiblegenderid = 1 OR eligiblegenderid = 3)
AND ((EligibleMinAge <= 28 AND EligibleMaxAge >= 28) OR (EligibleMinAge <= 28 AND EligibleMaxAge is null) OR (EligibleMinAge IS NULL AND EligibleMaxAge >= 28))
AND (HYID = 6 AND (hy.Disqualify = 0 OR hy.Disqualify IS NULL AND NOT EXISTS (SELECT * FROM hy WHERE t.id = hy.TrialID AND hy.Req =1)) OR HYID = 6 AND hy.req = 1)
AND (PDT_ID IN (1) AND ( pdt.Disqualify = 0 OR pdt.Disqualify IS NULL AND NOT EXISTS (select * from pdt where t.id = pdt.TrialID AND pdt.Req = 1)) OR PDT_ID IN (1) AND (pdt.Req = 1 AND (pdt.Disqualify = 0 or pdt.Disqualify is null )))
) AND ((3959 * acos(cos(radians(34.18)) * cos(radians(l.Latitude)) * cos(radians(l.Longitude) - radians(-118.46)) + sin(radians(34.18)) * sin(radians(l.Latitude)))) <= 300 OR l.Latitude IS NULL) AND t.IsPublished = 1 AND (t.StatusID = 1 OR t.StatusID = 2)
Я изменил / сократил некоторые имена таблиц только из соображений безопасности / конфиденциальности.
Edit:
Я думаю, что я близок к тому, чтобы заставить это работать, но я снова запутался в логике.
У меня есть следующий бит sql:
AND ( exists (SELECT * FROM pdt WHERE Req = 1 AND trialid = t.id AND pdT_ID IN (2) ) AND EXISTS (SELECT * FROM pdt WHERE Req = 1 AND trialid = t.id ) )
Я не уверен, как это структурировать. Эти два существующих утверждения должны сделать все это правдой в следующей комбинации:
Верно и Неверно
Правда правда
Ложь и ложь
Если это Ложь и Правда, тогда все это ложно. Другими словами, если существует Req = 1 И PDT_ID, помеченный как Req = 1, отсутствует в нашем списке (в приведенном выше примере список содержит только «2»), тогда верните false.
EDIT:
Я думаю, что я наконец получил это.
AND NOT EXISTS (SELECT * FROM pdt WHERE Disqualify = 1 AND trialid = t.id AND PDT_ID IN (2) )
AND NOT ( NOT exists (SELECT * FROM pdt WHERE Req = 1 AND trialid = t.id AND PDT_ID IN (2) ) AND EXISTS (SELECT * FROM pdt WHERE Req = 1 AND trialid = t.id ) )
Пока что это похоже на тестирование. Хотя я работаю только с двумя значениями PDT_ID. Если это решит мою проблему, я вернусь и дам кому-нибудь кредит за помощь.