Как удалить дубликаты и ненужные строки - PullRequest
0 голосов
/ 26 февраля 2020

Итак, у меня есть таблицы «Sample», «Test» и «Result», связанные друг с другом из базы данных, и я пытаюсь получить информацию с помощью MS Query. Каждый образец имеет один тест, и каждый тест может содержать около 20 результатов, введенных разными людьми.

Я хочу, чтобы образец отображался только в том случае, если введенное мной имя человека НЕ ​​связано с вводом ЛЮБОГО из результатов.

SELECT SAMPLE.SAMPLE_NUMBER, SAMPLE.TEXT_ID, SAMPLE.STATUS, SAMPLE.DATE_COMPLETED, SAMPLE.LOCATION, TEST.ANALYSIS, RESULT.ENTERED_BY

FROM DATABASE.RESULT RESULT, DATABASE.SAMPLE SAMPLE, DATABASE.TEST TEST

WHERE TEST.SAMPLE_NUMBER = SAMPLE.SAMPLE_NUMBER AND RESULT.TEST_NUMBER = TEST.TEST_NUMBER 
        AND ((TEST.ANALYSIS='ID_META' Or TEST.ANALYSIS='ID_RIBO' Or TEST.ANALYSIS='ID_BACTERIA' Or TEST.ANALYSIS='ID_MOULD') 
        AND (SAMPLE.STATUS='C') AND (SAMPLE.DATE_COMPLETED Is Not Null) 
        AND (RESULT.ENTERED_ON Between [Start Date] And [End Date]) 
        AND (RESULT.ENTERED_BY<>[Enter Name]))
ORDER BY SAMPLE.DATE_COMPLETED

Это код, который у меня есть до сих пор. но проблема в том, что если человек ввел один из 10 результатов, то тот же образец будет отображаться 9 раз и просто не будет отображаться в течение одного раза, когда он не вводил результат. Есть ли способ, которым я могу сказать, если он вообще вводил ЛЮБОЙ результат, то образец вообще не появится.

1 Ответ

1 голос
/ 26 февраля 2020

Когда вы обнаружите, что хотите ограничить строки условием, включающим несколько строк (например, «Я хочу каждый тест, в котором ни один из нескольких результатов не был введен этим человеком»), вы не можете сделать это с простыми условиями, такими как RESULT.ENTERED_BY<>[Enter Name]. Это касается только значения каждой строки, с которой вы в данный момент работаете. Вам нужен коррелированный подзапрос или аналитическая функция. Я думаю, что подзапросы легче начинать, и в вашем случае предложение NOT EXISTS имеет интуитивный смысл.

(я также собираюсь переписать это с использованием стандартного современного синтаксиса JOIN)

select SAMPLE.SAMPLE_NUMBER, SAMPLE.TEXT_ID, SAMPLE.STATUS, SAMPLE.DATE_COMPLETED, SAMPLE.LOCATION, TEST.ANALYSIS, RESULT.ENTERED_BY
from DATABASE.SAMPLE SAMPLE
join DATABASE.TEST TEST
    on TEST.SAMPLE_NUMBER = SAMPLE.SAMPLE_NUMBER
join DATABASE.RESULT RESULT
    on RESULT.TEST_NUMBER = TEST.TEST_NUMBER 
where (TEST.ANALYSIS in ('ID_META','ID_RIBO','ID_BACTERIA','ID_MOULD')
    and (SAMPLE.STATUS='C') and (SAMPLE.DATE_COMPLETED Is Not Null) 
    and (RESULT.ENTERED_ON Between [Start Date] And [End Date]) 
-- up until here, it's the same as your query
    and NOT EXISTS (select 1 
                    from DATABASE.TEST T2
                    join DATABASE.RESULT R2
                      on R2.TEST_NUMBER = T2.TEST_NUMBER
                    where T2.SAMPLE_NUMBER = SAMPLE.SAMPLE_NUMBER
                      and T2.ANALYSIS in ('ID_META','ID_RIBO','ID_BACTERIA','ID_MOULD')
                      and R2.ENTERED_ON Between [Start Date] And [End Date]
                      and R2.ENTERED_BY = [Enter Name])
ORDER BY SAMPLE.DATE_COMPLETED;

Итак, здесь мы говорим, чтобы вернуть все образцы, где «не существует» ни одного теста с любым результатом, который был введен указанным c человеком. (Я не уверен, что вам понадобится фильтр даты как для основного запроса, так и для подзапроса - и RESULT, и R2 - вам придется выяснить это на основе ваших данных.)

Редактировать: если вы хотите одну строку на выборку, просто удалите соединения TEST / RESULT из основного запроса:

select SAMPLE.SAMPLE_NUMBER, SAMPLE.TEXT_ID, SAMPLE.STATUS, SAMPLE.DATE_COMPLETED, SAMPLE.LOCATION
from DATABASE.SAMPLE SAMPLE
where (SAMPLE.STATUS='C') and (SAMPLE.DATE_COMPLETED Is Not Null) 
    and NOT EXISTS (select 1 
                    from DATABASE.TEST T2
                    join DATABASE.RESULT R2
                      on R2.TEST_NUMBER = T2.TEST_NUMBER
                    where T2.SAMPLE_NUMBER = SAMPLE.SAMPLE_NUMBER
                      and T2.ANALYSIS in ('ID_META','ID_RIBO','ID_BACTERIA','ID_MOULD')
                      and R2.ENTERED_ON Between [Start Date] And [End Date]
                      and R2.ENTERED_BY = [Enter Name])
ORDER BY SAMPLE.DATE_COMPLETED;
...