Autor Téma: dotaz nad mé síly  (Přečteno 911 krát)

Offline Vladimir64

  • Nováček
  • *
  • Příspěvků: 29
  • Karma: 0
    • Verze Delphi: 10.2
dotaz nad mé síly
« kdy: 30-07-2023, 18:58:37 »
Dobrý den, potřebuji vypočítat produkci jednotlivých oddělení po jednotlivých dnech, v tabulce jsou uvedena čísla kusů (jedná se o produkci textilního závodu). Čísla jsou unikátní. Dále čísla strojů, délku kusů v metrech, datum a čas kdy byl kus zpracován.

piece - číslo kusu ve formátu varchar(15)
mydate - datum kdy byl kus zpracován ve formátu date
mytime - čas kdy byl kus zpracováván ve formátu time
m - délka kusu v metrech ve formátu float

dále @specific_date je datum který zadávám na začátku dotazu a je to datum za který počítám produkci


Oddělení které počítám má několik strojů ale některé z nich mají více částí. V případě, že má stroj víc částí je v tabulce i víc záznamů. Každý záznam má ale stejné číslo stroje. Je vcelku jednoduché zjistit jestli na tom stroji ten kus už jednou byl a pokud ano podruhé ho nezapočítávat (nechci mít v produkci trojnásobné metry, pokud jeden a ten stejný kus prochází 3 částmi stejného stroje). Problém je v tom, že v technologických postupech existuje i varianta, kdy kus skutečně prochází strojem vícekrát (včetně jeho jednotlivých částí) Chci pro rozlišení toho jestli se jedná o jeden průchod (i když více částmi) nebo vícenásobný průchod, využít čas kdy daný kus byl zpracováván. Pokud tedy je ten kus na stejném stroji během jedné hodiny,nezapočítávat, je to v rámci jednoho průchodu strojem, pokud ale je časový rozdíl větší než 1 hodina započítávat. V tom případě se jedná skutečně o vícenásobný průchod strojem.
Vytvořil jsem dotaz kde vytvářím přechodnou tabulku temp_results, kam ukládám do jednotlivých řádků výsledky jednotlivých oddělení, nakonec to vyexportuji v textovém souboru a přechodnou tabulku smažu. Všechno funguje jen s tím jedním oddělením zápasím už celý den.

toto nepracuje korektně (na oddělení jsou 3 stroje s čísly 1001, 1002 a 1005) jen stroje 1001 a 1002 mají víc částí.

INSERT INTO temp_results (row_data)
SELECT CONCAT(@custom_text6, ';', REPLACE(FORMAT(SUM(m), 0), ',', ' '))
FROM (
    SELECT a.piece,
           CASE
               WHEN a.machine = '1005' THEN SUM(a.m)
               WHEN a.machine IN ('1001', '1002') THEN
                    CASE
                        WHEN (
                            SELECT TIMESTAMPDIFF(HOUR, MAX(CONCAT(b.mydate, ' ', b.mytime)), MAX(CONCAT(a.mydate, ' ', a.mytime)))
                            FROM av50 AS b
                            WHERE b.piece = a.piece AND b.machine IN ('1001', '1002') AND DATE(b.mydate) < @specific_date
                        ) > 1 THEN SUM(a.m)
                        ELSE 0
                    END
               ELSE 0
           END AS m
    FROM av50 AS a
    WHERE DATE(a.mydate) = @specific_date AND a.machine IN ('1001', '1002', '1005')
    GROUP BY a.piece, a.machine
) AS subquery
GROUP BY DATE(@specific_date);

najde se někdo kdo to dá na první dobrou? Snažil bych se dál, jen čas kdy to musím mít hotové se neúprosně blíží.

Offline Jan Fiala

  • Hrdina
  • ****
  • Příspěvků: 419
  • Karma: 4
    • Verze Delphi: 10.4.1
    • PSPad editor
Re:dotaz nad mé síly
« Odpověď #1 kdy: 31-07-2023, 12:38:07 »
jen tak na první pohled tam vidím problem:
Kód: [Vybrat]
CASE
                        WHEN (
                            SELECT TIMESTAMPDIFF(HOUR, MAX(CONCAT(b.mydate, ' ', b.mytime)), MAX(CONCAT(a.mydate, ' ', a.mytime)))
                            FROM av50 AS b
                            WHERE b.piece = a.piece AND b.machine IN ('1001', '1002') AND DATE(b.mydate) < @specific_date
                        ) > 1 THEN SUM(a.m)
                        ELSE 0
                    END

Kdyz je rozdil vic jak hodinu, tak spocitas, jinak davas natvrdo nulu a pritom bys mel pocitat jen ten jeden pruchod

Druhy problem, v tom subselectu mas DATE(b.mydate) < @specific_date a podle mne by tam melo byt DATE(b.mydate) = @specific_date

« Poslední změna: 31-07-2023, 12:40:22 od Jan Fiala »

Offline Jan Fiala

  • Hrdina
  • ****
  • Příspěvků: 419
  • Karma: 4
    • Verze Delphi: 10.4.1
    • PSPad editor
Re:dotaz nad mé síly
« Odpověď #2 kdy: 31-07-2023, 12:54:17 »
Zkus na to jit z druhe strany. Sectes vse a odectes od toho pripady, kdy se vejdes do hodiny. Doufam, ze MySQL umi Left Outer Join. Ten se napoji jen, pokud je splnena podminka, jinak vraci null

Kód: [Vybrat]
select a.machine, a,piece, sum(a.m - IfNull(b.m, 0))
from av50 as a
left outer join av50 as b on a.piece = b.piece and (a.machine <> '1005') and  TIMESTAMPDIFF(HOUR, MAX(CONCAT(b.mydate, ' ', b.mytime)), MAX(CONCAT(a.mydate, ' ', a.mytime))) < 1   
where DATE(a.mydate) = @specific_date AND a.machine IN ('1001', '1002', '1005')
GROUP BY a.piece, a.machine

Omlouvam se, pisu to z hlavy

Offline Vladimir64

  • Nováček
  • *
  • Příspěvků: 29
  • Karma: 0
    • Verze Delphi: 10.2
Re:dotaz nad mé síly
« Odpověď #3 kdy: 31-07-2023, 17:03:14 »
proč se omlouváš? Kéž bych já dokázal napsat složitý dotaz jen tak z hlavy. Já ho pracně skládám po částech, často způsobem pokus - omyl. Snad mě ale omlouvá, že nejsem IT profesionál jako mnozí na tomto fóru a s databázemi si zatím moc netykám. Stáhnu ze serveru aktuální data a jdu to vyzkoušet. Zatím díky. Dám vědět jak jsem dopadl.

Offline Jan Fiala

  • Hrdina
  • ****
  • Příspěvků: 419
  • Karma: 4
    • Verze Delphi: 10.4.1
    • PSPad editor
Re:dotaz nad mé síly
« Odpověď #4 kdy: 31-07-2023, 17:34:00 »
Jeste z te join podminky vyluc pripady, kdy je cas stejny (pridej and a.cas <> b.cas), at ti tam neco zustane

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 7352
  • Karma: 44
    • Verze Delphi: W11 + D11.3.1
Re:dotaz nad mé síly
« Odpověď #5 kdy: 01-08-2023, 08:30:45 »
O MySQL neviem nič. Uvedený SQL a jeho popis je pre mňa veľmi zložitý :o . Takže to bude len o tom, ako zvyknem postupovať. Možno Ti to pomôže.
Ak potrebujem pracovať len s časťou údajov, tak v takom prípade som si obľúbil konštrukciu WITH XX AS (SELECT ...)...
Výhody ktoré vidím ja:
  • samostatne si pripravím subselect-y - viem si skontrolovať ich výsledky
  • základný kód je omnoho čitateľnejší. Lebo napr. namiesto INNER JOIN (SELECT ...) mám jednoduché INNER JOIN XX
Bez Visual Query Builder sa nepohnem ;)
Win11 64b, Delphi 11.3.1, FireBird 4.01
Expert na kladenie nejasne formulovaných otázok.

Offline Vladimir64

  • Nováček
  • *
  • Příspěvků: 29
  • Karma: 0
    • Verze Delphi: 10.2
Re:dotaz nad mé síly
« Odpověď #6 kdy: 01-08-2023, 21:09:05 »
zatím to nejde. Zkouším opravit svůj původní dotaz podle první připomínky, ale vypadá to, že budu opravdu muset zkusit tu druhou navrhovanou konstrukci. Sečíst všechny metry a odečítat ty které splní uvedenou podmínku. Musím to ale přerušit, od 1.8. musím reportovat výrobu a musím dokončit vzhled reportu a jeho export. Dokud to nezvládnu budu muset toto jediné oddělení dopočítávat ručně. Ostatní jsou ok. To na pár dní není žádná tragédie, ale nechtěl bych to dělat dlouho. Budu pokračovat v tomto vlákně, jakmile to dořeším

Offline Jan Fiala

  • Hrdina
  • ****
  • Příspěvků: 419
  • Karma: 4
    • Verze Delphi: 10.4.1
    • PSPad editor
Re:dotaz nad mé síly
« Odpověď #7 kdy: 02-08-2023, 06:49:57 »
Odlaď si tu druhou část, abys měl jistotu, že tam máš to, co potřebuješ, tzn. napřed to vyber bez GROUP BY a vedle sebe v dotazu postav vysledky z A i B, abys vedel, co se ti bude sčítat. Něco jako

Kód: [Vybrat]
select a.machine, a,piece, a.m, a.mydate, a.mytime, b.machine, b.piece, b.m, b.mytime
from av50 as a
left outer join av50 as b on a.piece = b.piece and (a.machine <> '1005') and  TIMESTAMPDIFF(HOUR, MAX(CONCAT(b.mydate, ' ', b.mytime)), MAX(CONCAT(a.mydate, ' ', a.mytime))) < 1  and (a.mytime <> b.mytime)
where DATE(a.mydate) = @specific_date AND a.machine IN ('1001', '1002', '1005')

Měl přehledně vidět z A vše a z B pouze to, čeho se chceš zbavit.