Как определить, получаю ли я дублирование записей в MYSQL? - PullRequest
4 голосов
/ 28 октября 2011

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

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

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

Что яdo в запросе - это взять все пакеты, которые имеют задачи, и суммировать все предполагаемое время каждой задачи. Я суммирую все time_elapsed в batch_log и умножаю hours_open на количество машин этой операции.

Из-за этого у deburr должно быть максимум 120 часов, так как они открыты 24 часа в сутки, и есть 5 станций для удаления заусенцев.знаю, если вам нужна дополнительная информация.

SELECT 
  DATE(bl.start_time) as date_tracked,
  o.name as operation,
  SUM(TIME_TO_SEC(bl.time_elapsed)/ 3600)  as time_elapsed,
  SUM(t.estimated_nonrecurring + t.estimated_recurring) / 3600  as estimated,
  o.hours_open as hours_open,  
    (count(distinct m.id)) as machine_count,
  hours_open * (count(distinct m.id)) as total_hours,
  (sum(TIME_TO_SEC(bl.time_elapsed)) / 3600) / (count(distinct m.id)) as time_elapsed_usage
FROM
  batches b
INNER JOIN 
  tasks t on b.id = t.batch_id
INNER JOIN  
  batch_log bl on b.id = bl.batch_id
INNER JOIN
  operations o on b.operation_id = o.id 
INNER JOIN
  machines m  on b.operation_id = m.operation_id
WHERE 
  bl.time_elapsed < "8:00:00"

GROUP BY
  b.operation_id,
  DATE(bl.start_time)
ORDER BY date_tracked, o.id

Итак, я начал снова, и как только я дошел до этой точки, у меня, кажется, дублированиеза прошедшее время:

select 
  batches.operation_id,
  date(batch_log.start_time) as date,
  SEC_TO_TIME(SUM(TIME_TO_SEC(batch_log.time_elapsed))) as elapsed,
    sum(tasks.estimated_nonrecurring + tasks.estimated_recurring) as estimated_time

from
  batches
INNER JOIN batch_log on batches.id = batch_log.batch_id
INNER JOIN tasks on batches.id = tasks.batch_id
WHERE batches.id not in (
-1,
-2,
-3,
-4,
-5,
-6,
-7,
-8,
-9,
-10,
-11,
-12,
-13,
-14
)
group by Date(batch_log.start_time), operation_id 
order by batch_log.start_time, batches.operation_id

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

Ответы [ 5 ]

6 голосов
/ 28 октября 2011

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

Итак, для развития я начинаю с использования SELECT * и сначала прорабатываю свои объединения. Если это большой набор данных, я могу отфильтровать по классу where, чтобы выбрать только один набор записей, пакет в вашем случае. Затем я могу вернуться к исходным данным по одной таблице за раз и проверить свои результаты.

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

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

4 голосов
/ 28 октября 2011

Учитывая, что вы присоединяетесь к машинам в основном запросе, суммарные значения часов_открытого и оценочного значения уже раздуваются (умножаются) на количество машин, участвующих в каждой операции.

Самым простым решением было бы удалить внутреннее соединение с машинами в основном запросе, хотя этот запрос, вероятно, был бы более эффективным, если бы ссылка была сохранена и подзапросы для подсчета машин были заменены на count(distinct m.id). Суммированные значения часов_открытого и оценочного значений также должны быть разделены на count(distinct m.id), за исключением случаев, когда вы хотите, чтобы они были увеличены на количество компьютеров (в общем_часах, где необходимо удалить умножение на подзапрошенное значение).

4 голосов
/ 28 октября 2011

У вас есть присоединение к машинам, но вы никогда не используете его, и у вас есть подзапрос для получения количества машин.Они не должны быть оба в запросе.

Таким образом, я думаю, что ваша проблема в том, что вам нужно либо удалить объединение, либо удалить количество машин, использовать объединение машин в выбранном вами и добавить группумашины по вашему запросу.

1 голос
/ 04 ноября 2011

Уточнения, пожалуйста ...

Очевидно, Batch_Log несколько записей в пакете.
Таблица партий, отличный идентификатор партии.

Now, on to tasks, operations and machines. 
Can a batch have multiple tasks? 
Can a batch have multiple operations? 
Is the importance of distinct machines per operation critical?

Тем не менее, вот мой обзор вашей ситуации ... Во-первых, я получаю только время регистрации пакетных журналов менее 8:00:00. по вашему запросу. С этой агрегацией, предварительно сгруппированной в единый квалифицированный Пакеты, затем я могу сделать простое объединение пакетов и задач по этим идентификаторам пакетов. Я могу SUM () из задач, не беспокоясь о двойном счете в качестве стартового Основой является единичный идентификатор партии. Группировка всего этого по идентификатору партии упрощает Присоединение уровня NEXT к таблице операций и машин

Тогда, для агрегации, я предварительно агрегировал те, что они будут возвращать одну запись соответственно и уменьшить возможность возникновения декартовых ошибок COUNT () и SUM ().

В отношении машин. У вас есть машины, связанные с операция, но затем вы группируете по операции и дате. Тот Сказано, и кажется, что операция может (и делает) пересечь даты, одна машина будет учитываться каждый день. Будет ли это причиной некоторых возможные искаженные числа ??? Не уверен, не думал так далеко.

SELECT STRAIGHT_JOIN
      SmryByBatch.Operation_ID,
      SmryByBatch.Date_Tracked,
      SUM( SmryByBatch.Time_Elapsed ) Time_ElapsedByOpDate,
      SUM( SmryByBatch.Time_Elapsed ) / OpMachines.Machine_Count Time_ElapsedPerMachine,
      SUM( SmryByBatch.TaskEstByBatch ) TaskEstByOpDate,
      o.Name Operation,
      o.hours_open,
      OpMachines.Machine_Count,
      o.Hours_Open * OpMachines.Machine_Count as Total_Hours
   FROM 
       ( SELECT  
            b.Operation_ID,
            PreQuery.Batch_ID,
            PreQuery.Date_Tracked,
            PreQuery.TotalTimeElapsed / 3600 as Time_Elapsed,
            SUM( t.estimated_nonrecurring 
               + t.estimated_recurring ) / 3600 as TaskEstByBatch
         FROM 
            ( SELECT
                    bl.batch_id,
                    DATE( bl.Start_Time ) date_tracked,
                    SUM( bl.time_elapsed ) TotalTimeElapsed
                 FROM
                    batch_log bl
                 WHERE
                    bl.time_elapsed < "8:00:00"
                 GROUP BY
                    bl.batch_ID,
                    DATE( bl.Start_Time ) ) PreQuery

            JOIN batches b
               ON PreQuery.Batch_ID = b.ID

            JOIN Tasks t
               ON PreQuery.Batch_ID = t.Batch_ID

        GROUP BY
           b.Operation_ID,
           PreQuery.Batch_ID ) SmryByBatch

      JOIN Operations o
         ON SmryByBatch.Operation_ID = o.ID

         JOIN ( select m.Operation_ID,
                       COUNT(distinct m.id)  machine_count
                   from
                      machines m
                   group by
                      m.Operation_ID ) OpMachines
            ON o.ID = OpMachines.Operation_ID

   GROUP BY 
      SmryByBatch.Date_Tracked
      SmryByBatch.Operation_ID,

   ORDER BY
      SmryByBatch.Date_Tracked,
      SmryByBatch.Operation_ID
1 голос
/ 28 октября 2011

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

Если бы я был на вашем месте, я бы удалил агрегации и группы, по которым у вас осталась бы ваша необработанная дата, и любое дублирование было бы легко обнаружить.

SELECT 
  DATE(bl.start_time) as date_tracked,
  o.name as operation,
  bl.time_elapsed / 3600 as time_elapsed,
  t.estimated_nonrecurring + t.estimated_recurring / 3600  as estimated,
  o.hours_open as hours_open,  
  (select COUNT(id) from machines where operation_id=o.id) as machine_count,
  hours_open * (select COUNT(id) from machines where operation_id=o.id) as total_hours,
  (bl.time_elapsed / 3600) / (select COUNT(id) from machines where operation_id=o.id) as time_elapsed_usage
FROM
  batches b
INNER JOIN 
  tasks t on b.id = t.batch_id
INNER JOIN  
  batch_log bl on b.id = bl.batch_id
INNER JOIN
  operations o on b.operation_id = o.id 
ORDER BY date_tracked, o.id

EDIT:

Это дает вам что-то более осмысленное (непроверенное)?

SELECT 
  DATE(bl.start_time) as date_tracked,
  o.name as operation,
  SUM(TIME_TO_SEC(bl.time_elapsed)/ 3600)  as time_elapsed,
  SUM(t.estimated_nonrecurring + t.estimated_recurring) / 3600  as estimated,
  SUM(o.hours_open) as total_hours,  
    count(distinct m.id) as machine_count,
  (sum(TIME_TO_SEC(bl.time_elapsed)) / 3600) / (count(distinct m.id)) as time_elapsed_usage
FROM
  batches b
INNER JOIN 
  tasks t on b.id = t.batch_id
INNER JOIN  
  batch_log bl on b.id = bl.batch_id
INNER JOIN
  operations o on b.operation_id = o.id 
INNER JOIN
  machines m  on b.operation_id = m.operation_id
WHERE 
  bl.time_elapsed < "8:00:00"
GROUP BY
  b.operation_id,
  DATE(bl.start_time)
ORDER BY date_tracked, o.id

EDIT2:

Это дает вам что-то более осмысленное (непроверенное)?

SELECT 
  DATE(bl.start_time) as date_tracked,
  o.name as operation,
  TIME_TO_SEC(bl.time_elapsed)/ 3600 as time_elapsed,
  SUM(t.estimated_nonrecurring + t.estimated_recurring) / 3600  as estimated,
  SUM(o.hours_open) as total_hours,  
    count(distinct m.id) as machine_count,
  (TIME_TO_SEC(bl.time_elapsed) / 3600) / (count(distinct m.id)) as time_elapsed_usage
FROM
  batches b
INNER JOIN 
  tasks t on b.id = t.batch_id
INNER JOIN  
  batch_log bl on b.id = bl.batch_id
INNER JOIN
  operations o on b.operation_id = o.id 
INNER JOIN
  machines m  on b.operation_id = m.operation_id
WHERE 
  bl.time_elapsed < "8:00:00"
GROUP BY
  b.operation_id,
  DATE(bl.start_time)
ORDER BY date_tracked, o.id
...