Sqlalchemy используя ~ с and_, or_ - PullRequest
0 голосов
/ 16 июня 2019

У меня есть выражение:

recent_oa = db_session.query(exists().where(
    and_(
        and_(Jobs.candidate_id == candidate_id, Jobs.interview_type == 'EVALUATION', Jobs.disposition_date < datetime.now()-timedelta(days=1)),
        ## I want this to evaluate to be True
        and_(~Jobs.candidate_id == candidate_id, Jobs.interview_type == 'IN_HOUSE', Jobs.disposition_date > '2017-01-01'),
        ## and I want this to evaluate to False    
    )
)).scalar()

recent_oa
>> True

, чтобы recent_oa оценивалось как True

Я хочу создать несколько условий, которые, если первая строка оценивается как True, а затем остальные строки оцениваются как False, recent_oa будет оцениваться как True

Как бы я написал это выражение? как у меня, похоже, не работает.

1 Ответ

0 голосов
/ 16 июня 2019

Вам нужно префикс выражение, которое нужно инвертировать с помощью ~, поэтому ~ and_(...).

Обратите внимание, что существуют операторы и функции для всех операторов логической логики. ~ также доступно как not_() функция , и, аналогично, and_() можно выразить с помощью &, а or_() можно выразить с помощью |. Я бы придерживался одного стиля или другого, а не обоих.

Таким образом, ваши требования могут быть выражены как

and_(
    and_(
        Jobs.candidate_id == candidate_id,
        Jobs.interview_type == 'EVALUATION',
        Jobs.disposition_date < datetime.now()-timedelta(days=1)
    ),

    not_(
        and_(
            not_(Jobs.candidate_id == candidate_id),
            Jobs.interview_type == 'IN_HOUSE',
            Jobs.disposition_date > '2017-01-01'
        )
    )
)

или как

(
    (
        (Jobs.candidate_id == candidate_id)
        & (Jobs.interview_type == 'EVALUATION')
        & (Jobs.disposition_date < datetime.now()-timedelta(days=1))
    )

    & (
        ~ (
            ~ (Jobs.candidate_id == candidate_id)
            & (Jobs.interview_type == 'IN_HOUSE')
            & (Jobs.disposition_date > '2017-01-01')
        )
    )
)

Поскольку операторы ~, & и | имеют меньший приоритет, чем операторы сравнения , вам необходимо использовать (...) скобки вокруг каждого из приведенных выше тестов, чтобы убедиться, что операторы применяется ко всем column == value и column < value тестам.

Я не уверен на 100%, что вы хотели использовать not_(Jobs.candidate_id == candidate_id), но если бы вы это сделали, то я просто использовал бы != там, так что Jobs.candidate_id != candidate_id и отбросил бы условие not_() в этом тесте.

Далее, запрос в любом случае, вероятно, не даст правильных результатов. Он скажет вам, если есть 1 или более строк, которые соответствуют вашим критериям, таким образом, строки, где совпадает идентификатор кандидата, и есть конкретные условия для типа интервью и даты проведения. То, что он не сделает, скажет вам, если есть только таких строк, которые соответствуют. Так что, если есть такие строки:

 candidate_id  |  disposition_date |  interview_type
---------------|-------------------|-----------------
 42            | 2018-01-01        | EVALUATION
 42            | 2018-01-02        | IN_HOUSE

тогда вы получите True, потому что есть 1 строка, соответствующая вашим критериям. Строка IN_HOUSE отфильтрована. Вы не получите False здесь, потому что не имеет значения, что другая строка существует для фильтра.

В этом случае вы хотите использовать логическую логику выражения NOT в отдельных предложениях EXISTS, , а не в условиях , поэтому наличие второй строки приводит к результату False, противостоящему True для другой строки:

SELECT id
FROM jobs
WHERE
    EXISTS(candidate_id = ? AND interview_type = ? AND disposition_date < ?)
    AND NOT EXISTS(candidate_id = ? AND interview_type = ? AND disposition_date > ?)

поэтому создайте два отдельных существующих запроса :

candidate = db_session.query(Jobs).filter(Jobs.candidate_id == candidate_id)
has_evaluation = (
    candidate
    .filter(Jobs.interview_type == 'EVALUATION')
    .filter(Jobs.disposition_date < datetime.now() - timedelta(days=1))
)
has_inhouse = (
    candidate
    .filter(Jobs.interview_type == 'IN_HOUSE')
    .filter(Jobs.disposition_date > '2017-01-01')
)
recent_oa = (
    db_session.query(Jobs.id)
    .filter(has_evaluation.exists())
    .filter(not_(has_inhouse.exists())) # or .filter(~has_inhouse.exists())
    .scalar()
)

Используется метод Query.exists() для создания отдельных EXISTS условий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...