Расчет отставания SQL (MS Access) - PullRequest
0 голосов
/ 25 марта 2009

Мне нужно рассчитать отставание по таблице: компоненты (ProductId, ComponentId, Status, StatusDate) где ComponentId, Status и StatusDate являются первичными ключами. ProductId - это внешний ключ. Пример:

prod1, comp1, 01, 05/01/2009<br/> prod1, comp1, 02, 05/01/2009<br/> prod1, comp1, 03, 06/01/2009<br/> prod1, comp1, 01, 07/01/2009<br/> prod1, comp1, 02, 20/01/2009<br/> prod2, comp2, 01, 22/01/2009<br/> prod1, comp1, 02, 23/01/2009<br/> prod1, comp1, 03, 31/01/2009<br/>
По сути, я пытаюсь рассчитать количество Компонентов в неделю в статусе ниже 03. Конечный пользователь вводит интервальную дату, поэтому мне нужно показать все недели в интервале, даже если в течение недели не было невыполненных работ. Ожидаемый результат, когда конечный пользователь вводит 01/01 / 2009-22 / 01/2009:

Week, Backlog<br/> 1,NULL/0<br/> 2,1<br/> 3,1<br/> 4,2<br/>
Пояснение к неделе 2: comp1 достигает статуса 03 на неделе, но затем возвращается к состоянию 01
Любая помощь приветствуется, спасибо

Ответы [ 2 ]

1 голос
/ 25 марта 2009

Я немного догадываюсь о том, что вы пытаетесь сделать, но вот мое лучшее предположение:

Во-первых, в вашей базе данных должна быть таблица календаря:

CREATE TABLE Calendar (
     calendar_date DATETIME NOT NULL,
     week_number INT NOT NULL,
     CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED (calendar_date)
)
GO

INSERT INTO Calendar (calendar_date, week_number) VALUES ('1/1/2009', 1)
INSERT INTO Calendar (calendar_date, week_number) VALUES ('2/1/2009', 2)
etc.

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

Теперь к вашей проблеме:

SELECT
     CAL.week_number,
     COUNT(DISTINCT C.component_id)
FROM
     Calendar CAL
LEFT OUTER JOIN Components C ON
     C.status_date = CAL.calendar_date AND
     C.status IN ('01', '02')
WHERE
     CAL.calendar_date BETWEEN @start_date AND @end_date
GROUP BY
     CAL.week_number

Я использовал IN для статуса, так как вы используете строки, поэтому "<'03'" не всегда может дать вам то, что вы хотите. «1» меньше, чем «03» в вашем уме? </p>

Кроме того, если на какой-либо из ваших дат имеется компонент времени, проверки на равенство и МЕЖДУ могут потребоваться изменить.

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

SELECT
     CAL.week_number,
     COUNT(DISTINCT C.component_id)
FROM
     Calendar CAL
LEFT OUTER JOIN Components C ON
     C.status_date <= CAL.calendar_date AND
     C.status IN ('01', '02')
LEFT OUTER JOIN Components C2 ON
     C2.component_id = C.component_id AND
     C2.status_date > C.status_date AND
     C2.status_date <= CAL.calendar_date
WHERE
     CAL.calendar_date BETWEEN @start_date AND @end_date AND
     C2.component_id IS NULL
GROUP BY
     CAL.week_number

Хотя я не уверен, где продукт подходит ко всему этому.

0 голосов
/ 25 марта 2009

Это частичный ответ, поскольку я не вижу, откуда в вашем примере берется 3-я неделя (11-18 января 2009 г.). Он иллюстрирует использование таблицы счетчиков для получения строки для пропущенных значений.

SELECT Counter,WeekNo, CountofStatus FROM Counter LEFT JOIN
    (SELECT Format([StatusDate],"ww") AS WeekNo, COUNT(c.Status) AS CountOfStatus
    FROM components c
    WHERE c.StatusDate BETWEEN #1/1/2009# AND #1/22/2009#
    AND c.Status<3
    GROUP BY Format([StatusDate],"ww")) Comp
ON Val(Comp.Weekno)=Counter.Counter   
WHERE Counter.Counter>=Val(Format(#1/1/2009#,"ww"))
AND Counter.Counter<=Val(Format( #1/22/2009#,"ww"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...