SQL две таблицы различных подсчетов с соединением

У меня две таблицы.

Таблица 1 содержит заказы и коды клиентов. В таблице 2 приведены заказы с кодами выпуска.

Мне нужно иметь возможность возвращать отдельное количество заказов по клиенту из таблицы 1 вместе с отдельным количеством заказов по клиенту с кодом проблемы «F» из таблицы 2. Тогда последнее поле будет соотношением двух. Количество выпусков / количество заказов. Я использую AS400 / DB2 SQL. Любая помощь будет принята с благодарностью.

Customer ORcnt IScnt IssueRatio cust1 450 37 0.082 cust2 255 12 0.047 cust3 1024 236 0.230 cust4 450 37 0.082


person David    schedule 12.12.2014    source источник
comment
Трудно помочь вам, не зная структуры ваших таблиц с образцами данных, которые относятся к желаемым результатам. Кроме того, люди будут более склонны помочь, если вы покажете код, который вы пробовали до сих пор, и почему он не сработал.   -  person Tab Alleman    schedule 12.12.2014


Ответы (3)


Вы можете использовать outer join для своей таблицы проблем и count с distinct. Что-то вроде этого в зависимости от ваших определений таблиц:

select o.customercode, 
       count(distinct o.orderid), 
       count(distinct i.orderid), 
       count(distinct i.orderid)/count(distinct o.orderid) ratio
from table1 o
      left join table2 i on o.orderid = i.orderid and i.issuecode = 'F'
group by o.customercode

Некоторым базам данных потребуется преобразовать соотношение в десятичное число - я не уверен насчет db2. При необходимости можно умножить результат на 1,0:

1.0*count(distinct i.orderid)/count(distinct o.orderid)

Кроме того, вам может не понадобиться distinct с count - в зависимости от ваших данных ...

person sgeddes    schedule 12.12.2014
comment
Большое вам спасибо, сэр, вы только что вытащили меня из безвыходной ситуации! - person David; 12.12.2014

Если я правильно понял, это join запрос вместе с условной агрегацией:

select t1.customer, count(*) as ordercnt,
       sum(case when issuecode = 'F' then 1 else 0 end) as issuecnt,
       avg(case when issuecode = 'F' then 1.0 else 0 end) as issuep
from table1 t1 join
     table2 t2
     on t1.orderid = t2.orderid
group by t1.customer;
person Gordon Linoff    schedule 12.12.2014
comment
Что 1.9 делает для вас здесь? И я думаю, вам понадобится ваш sum(...)/count(*), чтобы получить соотношение, если я не неправильно понял. - person sgeddes; 12.12.2014
comment
Это должно быть 1.0, и проще использовать avg(), чем делать деление. - person Gordon Linoff; 12.12.2014
comment
Я думаю, что оба варианта верны. Мне не хватало части 1.0 в моем скрипте. Спасибо ребята! - person David; 12.12.2014

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

SELECT t.customer,
       count(t.orderID_All),
       count(t.orderID_F),
       count(t.orderID_F)/count(t.orderID_All)
FROM
  (SELECT orders.customer,
          orders.orderID AS orderID_All,
          issues.orderID AS orderID_F /*assuming primary/unique key is customer-orderID*/
   FROM table1 orders
   LEFT OUTER JOIN /*you want *all* orders on the left and just orders w/ 'F' on the right*/
     (SELECT DISTINCT orderID
      FROM table2
      WHERE issuecode = 'F') issues ON orders.orderID = issues.orderID) t
GROUP BY t.customer;
person albielin    schedule 12.12.2014