Запрос, соединяющий три таблицы и получающий счет для одного поля, не возвращающий нулевых значений - PullRequest
0 голосов
/ 17 декабря 2018

У меня есть три таблицы: Dept, DocType, Documents.Мне нужен список всех DocTypes с соответствующим им Dept. и количеством документов для каждого DocType на Dept. В каждой таблице есть поля, чтобы правильно связать их.Моя проблема в том, что я правильно получаю счет, но типы документов, у которых нет документов, не отображаются в результатах как ноль.

Я хочу:

Accounting    Faxes   3
Accounting    Memos   0
Accounting    Misc    10

Но яполучаю:

Accounting    Faxes   3
Accounting    Misc    10

Вот мой запрос.Есть идеи?

select DE.DeptName, DT.DocTypeID, COUNT(Docs.DocNumber)
from DocTypes as DT
left join Documents as Docs on Docs.DocTypeID = DT.DocTypeID
left join Dept as DE on DE.DeptID = Docs.DeptID
group by DT.DocTypeID, DE.DeptName
order by DE.DeptName, DT.DocTypeID

Таблица Dept имеет: DeptID, DeptName

Таблица DocType имеет: DeptID, DocTypeID

Таблица документов имеет: DeptID, DocTypeID, DocNumber

Есть идеи?

Ответы [ 7 ]

0 голосов
/ 17 декабря 2018

Попробуйте этот код,

SELECT 
    DE.DeptName, DT.DocTypeID, ISNULL(COUNT(Docs.DocNumber), 0)
FROM
    DocTypes AS DT
        LEFT JOIN
    Documents AS Docs ON Docs.DocTypeID = DT.DocTypeID
        LEFT JOIN
    Dept AS DE ON DE.DeptID = Docs.DeptID
GROUP BY DT.DocTypeID , DE.DeptName
ORDER BY DE.DeptName , DT.DocTypeID
0 голосов
/ 17 декабря 2018

Это к вашему сведению, мы пересмотрели наши требования и больше не нуждаемся в подсчете для включения нулей.Я действительно ценю все ваши предложения и сохранил ветку, чтобы продолжить работу над ней, когда позволит время.

0 голосов
/ 17 декабря 2018

Сначала вам нужен перекрестный продукт всех типов документов и всех отделов

Причина, по которой это работает, заключается в том, что перекрестный продукт дает нам список всех возможных вещей для подсчета.Когда мы выберем из него это, мы узнаем, есть ли что-то, что мы хотим сосчитать, чего нет.В SQL вы должны думать в наборах ... это дает нам множество вещей для подсчета.

Так что мы делаем что-то вроде следующего (я все еще не на 100%, какая таблица имеет какие данные- В этом случае я предполагаю, что таблица документов будет иметь все типы документов, а таблица Dept будет иметь все отделы.)

 SELECT DocTypeID, DeptID
 FROM (SELECT DISTINCT DocTypeID FROM Documents)
 CROSS JOIN (SELECT DISTINCT DeptID FROM Dept)

Затем мы используем это для группировки и объединения с остальными данными.

 select DE.DeptName, docs.DocTypeID, COUNT(Docs.DocNumber)
 FORM (
   SELECT DocTypeID, DeptID
   FROM (SELECT DISTINCT DocTypeID FROM Documents)
   CROSS JOIN (SELECT DISTINCT DeptID FROM Dept)   
 ) AS base 
 left join Documents as Docs on Docs.DocTypeID = base.DocTypeID
 left join Dept as DE on DE.DeptID = base.DeptID
 group by docs.DocTypeID, DE.DeptID
 order by DE.DeptID, docs.DocTypeID
0 голосов
/ 17 декабря 2018

Вы должны попробовать следующий запрос:

select DE.DeptName, DT.DocTypeID, COUNT(Docs.DocNumber)
  from Dept as DE
  left join DocTypes as DT on DT.DeptID = DE.DeptID
  left join Documents as Docs on (Docs.DeptID = DE.DeptID and Docs.DocTypeID = DT.DocTypeID)
 group by DT.DocTypeID, DE.DeptName
 order by DE.DeptName, DT.DocTypeID

Важно, чтобы таблица DocTypes была объединена перед таблицей Documents, если вы хотите, чтобы она была в вашем наборе результатов.Если сначала присоединится таблица Documents, и для какого-либо типа документа нет записи, то в первую очередь нечего будет присоединять.

Кроме этого, я бы также добавил Docs.DeptID = DE.DeptID к вашемуприсоединяйтесь, так как вы хотите считать документы только за один DeptId.Рекомендуется объединять таблицы, используя все общие столбцы, как вы указали:

Таблица Dept имеет: DeptID, DeptName

Таблица DocType имеет: DeptID, DocTypeID

Таблица документов содержит: DeptID, DocTypeID, DocNumber

Без него вы бы умножили свои результаты так, как вы написали их в вопросе.В любом случае сумма подсчитанных значений должна быть точно такой же, как и количество строк в самой таблице Docs, так что это способ проверить, умножаете ли вы ваши результаты.

Надеюсь, я помог!

0 голосов
/ 17 декабря 2018

Вы не упоминаете, какую СУБД вы используете, поэтому ответ будет разным, но на примере Oracle вы можете использовать NVL (COUNT (Docs.DocNumber), 0).В основном, если COUNT (Docs.DocNumber) возвращает NULL, вместо этого он возвращает 0.В любой СУБД, которую вы используете, будет что-то похожее.

0 голосов
/ 17 декабря 2018

Переключите joins.Причина, по которой вы не получаете типы документов, состоит в том, что вы начинаете свой запрос с типов документов, которые могут быть нулевыми - поэтому нечего «присоединяться».Начните свой запрос с данных, которые всегда присутствуют, например dept.Попробуйте это:

select 
    DE.DeptName, 
    DT.DocTypeID, 
    COUNT(Docs.DocNumber)
from 
    Dept as DE
left join 
    Documents as Docs on DE.DeptID = Docs.DeptID
left join 
    DocTypes as DT on Docs.DocTypeID = DT.DocTypeID
group by 
    DT.DocTypeID, 
    DE.DeptName
order by 
    DE.DeptName, 
    DT.DocTypeID
0 голосов
/ 17 декабря 2018

Можете ли вы попробовать этот запрос

SELECT DE.deptname, 
       DT.doctypeid, 
       Count(Docs.docnumber) 
FROM   dept AS DE 
       LEFT JOIN documents AS Docs 
              ON DE.deptid = Docs.deptid 
       LEFT JOIN doctypes AS DT 
              ON Docs.doctypeid = DT.doctypeid 
GROUP  BY DT.doctypeid, 
          DE.deptname 
ORDER  BY DE.deptname, 
          DT.doctypeid 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...