У меня есть одна большая таблица Audit с тысячами записей отклоненных требований. Каждый поступает от поставщика и имеет причину отказа и статус. Только id уникален.

id |      denial      |   supplier    | status
---|------------------|---------------|---------
 1 | Duplicate claim  | ACME          | Adjusted
 2 | Not authorized   | Umbrella Corp | Adjusted
 3 | Not authorized   | Stark Ind.    | Adjusted
 4 | Rec'd after due  | ACME          | Override
 5 | Duplicate claim  | Stark Ind.    | Adjusted
... etc

Что мне нужно, так это 5 основных причин отказа для заявлений о статусе «Скорректированный» по количеству записей и лучший поставщик по количеству записей для каждой из этих причин отказа.

denial          | cnt_denial | top_supplier  | cnt_top_supplier
----------------|------------|---------------|-----------------
Not authorized  | 917        | Stark Ind.    | 351
Duplicate claim | 685        | Stark Ind.    | 195
Not in contract | 525        | ACME          | 216
Rec'd after due | 512        | Umbrella Corp | 500
Explosions      | 349        | ACME          | 231

Я пробовал много способов, в основном пытаясь адаптировать другие, в чем-то похожие решения, но здесь я переоцениваю свои скудные знания SQL и расстраиваюсь. Некоторые решения, которые я пробовал, не работают в MS Access (2010). Для начала я создал два запроса, но у меня возникли проблемы с объединением их так, как мне нужно.

Этот запрос возвращает именно те данные о причине отказа, которые мне нужны:

SELECT TOP 5 denial, Count(*) AS cnt_denial
FROM Audit
GROUP BY status, denial
HAVING status="Adjusted"
ORDER BY Count(*) DESC;

И в этом запросе есть количество групп отказов / поставщиков в таблице. Я не уверен, как найти лучшего поставщика по каждой причине отказа, что, кажется, должно быть простым, но у меня проблемы. РЕДАКТИРОВАТЬ: это моя основная проблема. Если я смогу найти единственного ведущего поставщика по каждой причине отказа, я смогу выяснить, как присоединиться. Я пробовал использовать MAX, но пока не добился успеха. /РЕДАКТИРОВАТЬ

SELECT denial, supplier, Count(*) AS cnt_supplier
FROM Audit
GROUP BY denial, supplier, status
HAVING status="Adjusted"
ORDER BY Count(*) DESC;

Мне нужен один запрос, так как я просто передам его из Excel через ADO. Любая помощь будет очень признательна.

3
Phi Zeroth 6 Сен 2016 в 19:30

3 ответа

Лучший ответ

Я не знаю, правильно ли это Access SQL. Это не потребует особой настройки, если это не так:

select
    d.denial,
    d.cnt_denial,
    ds.supplier as top_supplier,
    ds.cnt_supplier as cnt_top_supplier
from
    (
        select top 5 denial, count(*) as cnt_denial
        from Audit
        where status = 'Adjusted'
        group by denial
        order by count(*) desc
    ) d
    inner join
    (
        select denial, supplier, count(*) as cnt_supplier
        from Audit
        where status = 'Adjusted'
        group by denial, supplier
    ) ds
        on ds.denial = d.denial
where not exists (
    select 1
    from Audit as a2
    where a2.status = 'Adjusted'
        and a2.denial = ds.denial and a2.supplier <> ds.supplier
    group by a2.supplier
    having count(*) > ds.cnt_supplier
        /* or count(*) = ds.cnt_supplier and a2.supplier < ds.supplier -- tiebreaker */
)
order by d.cnt_denial desc, ds.supplier

Используя top 5, он захватывает только пять строк независимо от связей. Затем первая верхняя часть в группе обрабатывается с помощью подзапроса, и в этом случае вы должны включить связи и потенциально получить более пяти строк в окончательном результате. Нетрудно включить связи на уровне отказа, если вам это нужно, или разорвать связи и исключить их из рейтинга поставщиков.

РЕДАКТИРОВАТЬ: Я собрал вместе некоторые тестовые данные, и выяснилось, что разрешение конфликтов работает на SQL Server. http://rextester.com/ZEWJ43486

1
shawnt00 7 Сен 2016 в 16:33

Похоже, ты проделал всю тяжелую работу.

Одно из решений - проверить включение причины отказа во второй запрос.

Сохраните свой первый запрос как qTop5Reasons

SELECT TOP 5 denial, Count(*) AS cnt_denial
FROM Audit
GROUP BY status, denial
HAVING status="Adjusted"
ORDER BY Count(*) DESC;

Измените ваш второй запрос, чтобы ограничить результаты на основе причин в этом запросе:

SELECT Audit.denial, Audit.supplier, Count(*) AS cnt_supplier
FROM Audit
WHERE (Audit.denial In (SELECT denial FROM qTop5Reasons))
GROUP BY Audit.denial, Audit.supplier, Audit.status
HAVING (((Audit.[status])="Adjusted"))
ORDER BY Count(*) DESC;
0
dbmitch 6 Сен 2016 в 17:00

Вам следует попробовать Inner join. Попробуй это

SELECT A.DENIAL, A.Cnt_Denial,B.Supplier as TOP_SUPPLIER, B.Cnt_supplier as           
TOP_CNT_SUPPLIER
FROM 
(SELECT TOP 5 denial, Count(*) AS cnt_denial
 FROM Audit
 GROUP BY status, denial
 HAVING status="Adjusted"
 ORDER BY Count(*) DESC) AS A INNER JOIN 
 (SELECT TOP 5 denial, supplier, Count(*) AS cnt_supplier
 FROM Audit
 GROUP BY denial, supplier, status
 HAVING status="Adjusted"
 ORDER BY Count(*) DESC) AS B
 ON A.DENIAL = B.DENIAL
0
bp89 7 Сен 2016 в 12:00