0

報告しようと思っています。特定の顧客のマシンのリストと、そのマシンに投入された時間と材料の合計を提供することになっています。

次の例では、問題を明確にするために、さまざまな分野の材料と時間の合計を選択しています。しかし、私は本当に材料を1時間合計してから、機械分野ごとにグループ化したい.

マシンのリストと時間のコストを問題なく照会できます。

SELECT CONCAT(`customer`.`PREFIX`, `wo`.`machine_id`) AS `machine`, 
       ROUND(COALESCE(SUM(`wohours`.`length` * `wohours`.`price`), 0), 2) AS `hours`

FROM `wo`
JOIN `customer` ON `customer`.`id`=`wo`.`customer_id`
LEFT JOIN `wohours` ON `wohours`.`wo_id`=`wo`.`id` AND `wohours`.`wo_customer_id`=`wo`.`customer_id` 
                    AND `wohours`.`wo_machine_id`=`wo`.`machine_id` AND `wohours`.`date`>=(CURDATE() - INTERVAL DAY(CURDATE() - INTERVAL 1 DAY) DAY) - INTERVAL 11 MONTH

WHERE `wo`.`customer_id`=1
GROUP BY `wo`.`machine_id`;

これにより、時間の正しい値が得られます。しかし、次のようにマテリアルを追加すると:

SELECT CONCAT(`customer`.`PREFIX`, `wo`.`machine_id`) AS `machine`, 
       ROUND(COALESCE(SUM(`wohours`.`length` * `wohours`.`price`), 0), 2) AS `hours`,
       ROUND(COALESCE(SUM(`womaterial`.`multiplier` * `womaterial`.`price`), 0), 2) AS `material`

FROM `wo`
JOIN `customer` ON `customer`.`id`=`wo`.`customer_id`
LEFT JOIN `wohours` ON `wohours`.`wo_id`=`wo`.`id` AND `wohours`.`wo_customer_id`=`wo`.`customer_id` 
           AND `wohours`.`wo_machine_id`=`wo`.`machine_id` AND `wohours`.`date`>=(CURDATE() - INTERVAL DAY(CURDATE() - INTERVAL 1 DAY) DAY) - INTERVAL 11 MONTH
LEFT JOIN `womaterial` ON `womaterial`.`wo_id`=`wo`.`id` AND `womaterial`.`wo_customer_id`=`wo`.`customer_id` 
           AND `womaterial`.`wo_machine_id`=`wo`.`machine_id` AND `wohours`.`date`>=(CURDATE() - INTERVAL DAY(CURDATE() - INTERVAL 1 DAY) DAY) - INTERVAL 11 MONTH

WHERE `wo`.`customer_id`=1
GROUP BY `wo`.`machine_id`;

その場合、時間と材料の値が両方とも正しくありません。

同様の問題を抱えている人が複数のクエリまたはサブクエリに分割することでこれを解決できる他のスレッドを読みました。しかし、この場合、それは不可能だと思います。

どんな助けでも大歓迎です。

//ジョン

4

1 に答える 1

1

あなたの他の読みは正しいです。結合のために、それらを独自の「サブクエリ」に入れる必要があります。おそらく無効な値を取得している理由は、材料テーブルにマシンごとに複数のレコードがあり、時間に基づいて元の結果がデカルトになるためです。そして、どれが多くて 1 つしかないのかわからないので、正しく見えません。

woHours と woMaterial を事前に集計するための最も内側の各クエリは、「wo_id と machine_id」ごとに 1 つのレコードを生成し、終了時に wo テーブルに結合します。これらの各クエリには、実行しようとしている単一の顧客 ID に関する基準があります。

次に、作業指示 (wo) テーブルに再結合されると、すべてのレコードが取得され、そのような時間や資料が存在しない場合に ROUND() と COALESCE() が適用されます。したがって、これは次のようなものの戻り値です

WO    Machine ID    Machine   Hours   Material
1     1             CustX 1   2       0
2     4             CustY 4   2.5     6.5
3     4             CustY 4   1.2     .5
4     1             CustX 1   1.5     1.2

最後に、これらすべてのエントリの SUM() を、マシン ID ごとに 1 つの行にロールアップできるようになりました。

Machine   Hours   Material
CustX 1   3.5     1.2
CustY 4   3.7     7.0


SELECT
      AllWO.Machine,
      SUM( AllWO.Hours ) Hours,
      SUM( AllWO.Material ) Material
   from
      ( SELECT
              wo.wo_id,
              wo.Machine_ID, 
              CONCAT(customer.PREFIX, wo.machine_id) AS machine, 
              ROUND( COALESCE( PreSumHours.MachineHours, 0), 2) AS hours,
              ROUND( COALESCE( PreSumMaterial.materialHours, 0), 2) AS material
           FROM 
              wo
                 JOIN customer 
                    ON wo.customer_id = customer.id

                 LEFT JOIN ( select wohours.wo_id,
                                    wohours.wo_machine_id,
                                    SUM( wohours.length * wohours.price ) as machinehours
                                from
                                   wohours 
                                where
                                       wohours.wo_customer_id = 1
                                   AND wohours.date >= ( CURDATE() - INTERVAL DAY( CURDATE() - INTERVAL 1 DAY) DAY) - INTERVAL 11 MONTH
                                group by
                                   wohours.wo_id,
                                   wohours.wo_machine_id ) as PreSumHours
                    ON wo.id = PreSumHours.wo_id 
                    AND wo.machine_id = PreSumHours.wo_machine_id 

                 LEFT JOIN ( select womaterial.wo_id,
                                    womaterial.wo_machine_id,
                                    SUM( womaterial.length * womaterial.price ) as materialHours
                                from
                                   womaterial
                                where
                                       womaterial.wo_customer_id = 1
                                   AND womaterial.date >= ( CURDATE() - INTERVAL DAY( CURDATE() - INTERVAL 1 DAY) DAY) - INTERVAL 11 MONTH
                                group by
                                   womaterial.wo_id,
                                   womaterial.wo_machine_id ) as PreSumMaterial
                    ON wo.id = PreSumMaterial.wo_id 
                    AND wo.machine_id = PreSumMaterial.wo_machine_id 
           WHERE 
              wo.customer_id = 1 ) AllWO
   group by
      AllWO.Machine_ID
于 2013-02-28T19:19:28.017 に答える