Як визначити, чи отримую дублювання записів у MYSQL?

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

Я роблю це, щоб визначити, які машини нам потрібно придбати більше. Все, що у нас є коефіцієнт використання більш ніж на 100%, це те, що ми перевищуємо.

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

Що я роблю в запиті, беруться всі партії, які мають завдання і сумуть приблизний час кожного завдання. Я сумую весь 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. Навіть якщо б я міг отримати відповідь на меншій заяві, я міг би досягти певного прогресу. Зараз працюю над іншими матеріалами.

4
Я б викидати інформацію про мою базу даних? Або опишіть таблиці?
додано Автор davidahines, джерело
Ви INNER JOIN ing до машини , хоча ви ніколи не користуєтеся ним (лише за допомогою підзапитів). Незважаючи на те, що ваш дизайн столу та деякі зразкові дані, це трохи важко зрозуміти, чи справді це проблема. Видалення його, швидше за все, підвищить продуктивність ... Га, деякий з цього було б набагато приємніше зібрати з CTEs.
додано Автор Clockwork-Muse, джерело
Можливо, ви просто найняли таких дивовижних людей, що вони можуть працювати більше 24 годин на день. Де робота може бути визначена як "запис". :)
додано Автор Nathan Feger, джерело
Правда, хоча ви пробували просто дивитись на записи одного комп'ютера протягом дня і розсудливість перевірили номери?
додано Автор Nathan Feger, джерело
Є причина, чому цей пост, незважаючи на щедрість, томився. Ви не повідомили нам свою схему бази даних. Як ми можемо налагодити ваш запит, доки точно не вказує структуру ваших таблиць і обмеження, що розміщені на них?
додано Автор rsj, джерело

5 Відповіді

Зазвичай, коли я хочу зробити щось складне, як це, я запускаю один шаблон одночасно і перевіряю дані, тому я знаю, що я повинен очікувати.

Отже, щоб почати розробку, я спочатку використовую SELECT * і спочатку розробляю мої з'єднання. Якщо це великий набір даних, я можу відфільтрувати за місцем розташування, щоб вибрати лише один набір записів, партію у вашому випадку. Тож я можу повернутися до вихідних даних за одним столом і перевірити мої результати.

Як тільки я знаю, що я випадково не зробив число записів занадто великим, тоді я починаю додавати в реальні стовпці, які я хочу. Замість формул я вибираю фактичні стовпці, які будуть в формулах. Це допомагає точно розробляти формули. Тож я додам у формули та будь-яку необхідну групу.

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

6
додано
+1 навчаю мене рибати.
додано Автор davidahines, джерело

З огляду на те, що ви приєднуєтеся до машин у основному запиті, сумарні значення hours_open та оцінюються, вже наповнюються (множаться) на кількість машин, що беруть участь у кожній операції.

Найпростішим рішенням було б видалення внутрішнього з'єднання з машинами в основному запиті, хоча запит, ймовірно, був би більш ефективним, якщо б посилання було збережено, а підзавдання для підрахунків машин замінено на підрахунок count (distinct m.id) . Підсумкові значення hours_open і estimated повинні також бути розділені на count (distinct m.id) , за винятком випадків, коли ви хочете, щоб вони були роздуті кількістю машин (у total_hours, де множення на підквартируе значення слід видалити)

4
додано
Спробуючи це, здається, все ще є дублювання, я відредагував запит.
додано Автор davidahines, джерело
+1 Snapback! :)
додано Автор Briguy37, джерело

Ви маєте приєднатися до машин, але ніколи не користуєтесь ними, і у вас є підзапит, щоб отримати рахунок машини. Вони не повинні бути в запиті.

Таким чином, я думаю, ваша проблема полягає в тому, що вам потрібно або видалити приєднання, або видалити рахунок машини, використати машини, що приєднаються до вибраного, і додавати групу за машинами до вашого запиту.

4
додано
+1 Snap! .......
додано Автор Mark Bannister, джерело

Роз'яснення будь ласка ...

Очевидно, 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() від завдань, не турбуючись про подвійне підрахунку як стартовий основою є одиничний ідентифікатор партії. Групувати все це за партійним ідентифікатором спрощує Наступний рівень приєднання до таблиці "Операції та машини"

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

Що стосується машин. У вас є машини, пов'язані з операція, але потім ви групуєте за операцією та датою. Це як кажуть, і, як видається, операція CAN (і робить) перетинає дати одна машина буде обліковуватися на кожен день. Чи це викликає деякі можливі перекошені числа ??? Не впевнений, не думав, що далеко.

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
додано
@ Да, Не знаю, чи навіть ви намагалися надати запит, але це має бути добре, оскільки група не вплине на ваш коментар до операцій 1: 1 пакетної операції
додано Автор DRapp, джерело
@ да, якщо ви могли б надати деякі зразкові дані у своєму оригінальному питанні, то чудово буде відображатися деякий час завантаження, операції, завдань. Якщо одна партія може охоплювати декілька операцій, то ви отримаєте дублювання часу, якщо завантаження партії/пакету не є специфічним для операції ... Навіть якщо дані зразка, що покажуть справжні відносини і де сплайси CAN йдуть та виконуватимуться, допоможуть .
додано Автор DRapp, джерело
Пакети мають операцію_ид.
додано Автор davidahines, джерело
Один пакет не може розповсюджувати операції.
додано Автор davidahines, джерело
Чи може партія мати кілька завдань? Так. Чи може партія мати кілька операцій? Чи важливо, щоб окремі машини на одну операцію були критичними? Я так не думаю, єдиною причиною, я роблю це, так, щоб я міг підрахувати кількість годин, коли станція відкрита, і помножити на кількість машин. EG: Deburr відкритий протягом 24 годин, існує п'ять машин для видалення збитків, тому 24 години * п'ять машин повинні дати мені 20 годин. Дякую за допомогу.
додано Автор davidahines, джерело

Це трохи здогадатися, але, як видно, у вас є кілька машин за операцію, а це означає, що ви будете збільшувати кількість годин на кількість машин.

Якщо б я був тобі, я б видалив агрегації та групу, яка повинна залишити вас вашим сировинним днем, і будь-яке копіювання має бути легко виявлено ..

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
1
додано
Схоже, все ще є деяке дублювання. Можливо ближче хоч.
додано Автор davidahines, джерело
Я відредагував мої дані, що це все більше корисно?
додано Автор davidahines, джерело
Тепер загальна кількість годин, здається, дублюється.
додано Автор davidahines, джерело
Ах! Час, що минув, не те, що я хочу збільшити, лише години. Я гетча Я спробую ваш запит.
додано Автор davidahines, джерело
Так, я насправді хочу розмножуватися на кількість машин за операцію. Як ніби ми маємо 8 годин на кожній фарбувальній станції, і у нас є дві машини для фарбування, то ми повинні мати 16 годин.
додано Автор davidahines, джерело
YEs, але ви помножуєте на кількість машин у вашому підзапиті, а потім знову, приєднавшись також ..
додано Автор StevieG, джерело
ти можеш трохи конкретизувати?
додано Автор StevieG, джерело
Я зробив ще одну пару змін, щоб спробувати розібрати time_elapsed, який також був обдурений ..
додано Автор StevieG, джерело