2016-02-02 2 views
2

Доброго дня,Неуверенные, как сделать несколько вложенного ЗЕЬЕСТ при использовании GROUP BY

В настоящее время я функционирующий код, который работает для определения количества открытых заказов на выполнении работ и количества закрытых заказов на выполнении работ в течение определенного периода времени. Теперь я хочу добавить количество рабочих заказов, которые были открыты до этого периода времени; У меня есть код, который дает результаты, которые я хочу, но у меня возникают трудности с выяснением того, как бы я сделал свой оператор select, встроенный в исходный код, поэтому мне не нужно назначать статическую дату. Будет легче показать вам, что у меня есть и что я ожидаю получить.

SELECT o.dateinfo 
    ,opened 
    ,closed 
FROM (
    SELECT MONTH(org_date) + (YEAR(org_date) * 100) AS dateinfo 
     ,COUNT(wo) AS opened 
    FROM wkaw 
    WHERE org_date >= DATEFROMPARTS(YEAR(GETDATE()) - 1, MONTH(GETDATE()), 01) 
    GROUP BY MONTH(org_date) + (YEAR(org_date) * 100) 
    ) o 
INNER JOIN (
    SELECT MONTH(cmpl_date) + (YEAR(cmpl_date) * 100) AS dateinfo 
     ,COUNT(wo) AS closed 
    FROM wkaw 
    WHERE cmpl_date >= DATEFROMPARTS(YEAR(GETDATE()) - 1, MONTH(GETDATE()), 01) 
     AND cmpl_date IS NOT NULL 
    GROUP BY MONTH(cmpl_date) + (YEAR(cmpl_date) * 100) 
    ) c ON o.dateinfo = c.dateinfo 
ORDER BY o.dateinfo 

Производит эти результаты в настоящее время

dateinfo | opened | closed 
-------------------------------- 
201502 | 285 | 587 
201503 | 519 | 345 
201504 | 494 | 398 
201505 | 415 | 430 
201506 | 578 | 465 
201507 | 409 | 646 
201508 | 501 | 417 
201509 | 430 | 347 
201510 | 491 | 983 
201511 | 657 | 455 
201512 | 468 | 366 
201601 | 723 | 1105 
201602 | 54 |  60 

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

SELECT COUNT(wo) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,02,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,02,01) 
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,03,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,03,01) 
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,04,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,04,01) 
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,05,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,05,01) 
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,06,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,06,01) 
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,07,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,07,01) 
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,08,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,08,01) 
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,09,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,09,01) 
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,10,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,10,01) 
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,11,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,11,01) 
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,12,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,12,01) 
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2016,01,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2016,01,01) 
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2016,02,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2016,02,01) 

Результаты для тех, кто являются

1 | 2187 
1 | 1885 
1 | 2059 
1 | 2155 
1 | 2140 
1 | 2253 
1 | 2016 
1 | 2100 
1 | 2183 
1 | 1691 
1 | 1893 
1 | 1995 
1 | 1613 

Эти цифры показывают, что я бы ожидать. Результаты, которые я хочу видеть, хотя это

dateinfo | open_wo_count | opened | closed 
--------------------------------------------------- 
201502 |  2187  | 285 | 587 
201503 |  1885  | 519 | 345 
201504 |  2059  | 494 | 398 
201505 |  2155  | 415 | 430 
201506 |  2140  | 578 | 465 
201507 |  2253  | 409 | 646 
201508 |  2016  | 501 | 417 
201509 |  2100  | 430 | 347 
201510 |  2183  | 491 | 983 
201511 |  1691  | 657 | 455 
201512 |  1893  | 468 | 366 
201601 |  1995  | 723 | 1105 
201602 |  1613  | 54 |  60 

Я пробовал разные способы, но все они производятся не-ожидаемые результаты, и я уверен, что это только потому, что я не знаю, как. Любая помощь будет оценена по достоинству.

Приветствия, Johnathan

+0

Обновлено, спасибо! Просто плохая привычка к капитализации названий –

+0

Я не уверен, что понимаю, но в прошлом я сделал скорый отчет о количестве заказов на работу и вам нужна таблица календаря (таблица, основной ключ которой - дата, охватывающая каждую возможную дату). Затем присоединитесь к соответствующим полям даты в ваших рабочих заказах и ответ выйдет. Может быть, лучше, если вы предоставите простой пример входных и выходных данных. –

ответ

0

Попробуйте использовать дополнительный выбор. Я также должен был преобразовать даты, чтобы иметь возможность сравнивать их с o.dateinfo. Таким образом, вам не нужно вручную создавать даты, поскольку они уже существуют в dateinfo.

SELECT o.dateinfo 
    , (SELECT COUNT(*) FROM wkaw WHERE (CONVERT(CHAR(6), cmpl_date, 112) >= o.dateinfo OR cmpl_date IS NULL) AND CONVERT(CHAR(6), org_date, 112) < o.dateinfo) AS open_wo_count 
    ,opened 
    ,closed 
FROM (
    SELECT MONTH(org_date) + (YEAR(org_date) * 100) AS dateinfo 
     ,COUNT(wo) AS opened 
    FROM wkaw 
    WHERE org_date >= DATEFROMPARTS(YEAR(GETDATE()) - 1, MONTH(GETDATE()), 01) 
    GROUP BY MONTH(org_date) + (YEAR(org_date) * 100) 
    ) o 
INNER JOIN (
    SELECT MONTH(cmpl_date) + (YEAR(cmpl_date) * 100) AS dateinfo 
     ,COUNT(wo) AS closed 
    FROM wkaw 
    WHERE cmpl_date >= DATEFROMPARTS(YEAR(GETDATE()) - 1, MONTH(GETDATE()), 01) 
     AND cmpl_date IS NOT NULL 
    GROUP BY MONTH(cmpl_date) + (YEAR(cmpl_date) * 100) 
    ) c ON o.dateinfo = c.dateinfo 
ORDER BY o.dateinfo 
+0

Мне было сложно усложнять инструкцию select, я думаю, что если бы я правильно прочитал это утверждение, вы используете dateinfo из оператора group, а затем меняете его на дату для создания предложения COUNT where? Это замечательно! Спасибо –

+0

Я действительно не понял, посмотрев на все команды множественного выбора, которые я мог бы сделать, выбрав внутри select; Я думал, что мне всегда нужно делать выбор из выбора, и это меня отбросило. Еще раз спасибо! –

0

Вы можете сделать таблицу, которая хранит все Признак начала месяца даты нужно. (Это может быть либо таблица полезности, которую вы генерируете один раз, либо это может быть временная таблица, которая генерируется «на лету»).

В вашем случае мы, вероятно, можем немного обмануть. До тех пор, пока у каждого месяца есть хотя бы один рабочий заказ в нем, мы можем использовать таблицу заказа на обслуживание, чтобы составить список нужных нам дат. Что-то вроде:

SELECT DISTINCT(DATEFROMPARTS(YEAR(org_date),MONTH(org_date),01)) AS d FROM wkaw 

Я считаю, что это даты, которые вы хотели. Теперь мы выбираем даты из этой «таблицы» вместе с подзапросом, который учитывает открытые рабочие процессы на каждую дату. Что-то вроде:

SELECT MONTHSTART.d, 
(SELECT COUNT(wo) FROM wkaw WHERE (cmpl_date >= MONTHSTART.d OR cmpl_date IS NULL) AND org_date < MONTHSTART.d) 
FROM (SELECT DISTINCT(DATEFROMPARTS(YEAR(org_date),MONTH(org_date),01)) AS d FROM wkaw) MONTHSTART 

Это не совсем дает вам окончательный запрос, но его довольно близко. Чтобы присоединиться к исходному запросу, попробуйте заменить SELECT MONTHSTART.d на SELECT MONTH(MONTHSTART.d) + (YEAR(MONTHSTART.d)*100) as dateinfo и объединить его с исходным запросом.

0

Если перекрестное соединение к столу Wkaw, то вы получите 13 дубликатов каждой записи в этой таблице. Затем вы можете сравнить cmpl_date и org_date с dateinfo, созданным в любом из двух подзапросов ранее.

Пример

SELECT o.dateinfo 
    ,SUM(Case when (cmpl_date >= DATEFROMPARTS(Left(o.dateinfo,4),Right(o.dateinfo,2),01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(Left(o.dateinfo,4),Right(o.dateinfo,2),01) THEN 1 ELSE 0 END) AS open_wo_count 
    ,MAX(opened) as opened 
    ,MAX(closed) as closed 
FROM (
    SELECT MONTH(org_date) + (YEAR(org_date) * 100) AS dateinfo 
     ,COUNT(wo) AS opened 
    FROM wkaw 
    WHERE org_date >= @DateStart 
    GROUP BY MONTH(org_date) + (YEAR(org_date) * 100) 
    ) o 
INNER JOIN (
    SELECT MONTH(cmpl_date) + (YEAR(cmpl_date) * 100) AS dateinfo 
     ,COUNT(wo) AS closed 
    FROM wkaw 
    WHERE cmpl_date >= @DateStart 
     AND cmpl_date IS NOT NULL 
    GROUP BY MONTH(cmpl_date) + (YEAR(cmpl_date) * 100) 
    ) c ON o.dateinfo = c.dateinfo 
CROSS JOIN Wkaw W 
GROUP BY o.dateinfo 
ORDER BY o.dateinfo 

Вы должны принять MAX или MIN из открытых и закрытых подсчетов (но это все будет то же самое, так нет проблем)