sql >> Databáze >  >> Database Tools >> phpMyAdmin

Vyberte záznam pouze v případě, že ten před tím, než má nižší hodnotu, trvá příliš dlouho a selže

Zde je řešení pro vaši otázku 1, které poběží mnohem rychleji, protože máte mnoho úplných skenů tabulky a závislých poddotazů. Zde budete mít nanejvýš jen jeden sken tabulky (a možná i dočasnou tabulku, v závislosti na tom, jak velká jsou vaše data a kolik máte paměti). Myslím, že to zde můžete snadno přizpůsobit své otázce. Otázka 2 (opravdu jsem ji nečetla) je pravděpodobně také zodpovězena, protože je nyní snadné pouze přidat where date_column = whatever

select * from (
    select
    t.*,
    if(@prev_toner < Remain_Toner_Black and @prev_sn = SerialNumber, 1, 0) as select_it,
    @prev_sn := SerialNumber,
    @prev_toner := Remain_Toner_Black
    from
    Table1 t
    , (select @prev_toner:=0, @prev_sn:=SerialNumber from Table1 order by SerialNumber limit 1) var_init
    order by SerialNumber, id
) sq  
where select_it = 1

EDIT:

Vysvětlení:

S tímto řádkem

    , (select @prev_toner:=0, @prev_sn:=SerialNumber from Table1 order by SerialNumber 

pouze inicializujeme proměnné @prev_toner a @prev_sn za běhu. Je to stejné, jako když tento řádek v dotazu vůbec nemáte, ale píšete před dotaz

SET @prev_toner = 0;
SET @prev_sn = (select serialnumber from your_table order by serialnumber limit 1);
SELECT ...

Proč tedy dotaz přiřadit hodnotu @prev_sn a proč objednávat podle sériového čísla? Pořadí podle je velmi důležité. Bez objednávky není zaručeno pořadí, ve kterém jsou řádky vráceny. Také budeme přistupovat k hodnotám předchozích řádků s proměnnými, takže je důležité, aby stejná sériová čísla byla „seskupena“.

Sloupce v klauzuli select se vyhodnocují jeden po druhém, takže je důležité, abyste nejprve vybrali tento řádek

if(@prev_toner < Remain_Toner_Black and @prev_sn = SerialNumber, 1, 0) as select_it,

než vyberete tyto dva řádky

@prev_sn := SerialNumber,
@prev_toner := Remain_Toner_Black

proč tomu tak je? Poslední dva řádky přiřadí proměnným pouze hodnoty aktuálních řádků. Proto v tomto řádku

if(@prev_toner < Remain_Toner_Black and @prev_sn = SerialNumber, 1, 0) as select_it,

proměnné si stále uchovávají hodnoty z předchozích řádků. A to, co zde děláme, není nic jiného než říkat:„Pokud je hodnota předchozích řádků ve sloupci Remain_Toner_Black menší než hodnota v aktuálním řádku a sériové číslo předchozích řádků je stejné jako skutečné sériové číslo řádků, vrátí 1, jinak vrátí 0."

Pak můžeme jednoduše říci ve vnějším dotazu "vyberte každý řádek, kde výše uvedené vrátilo 1".

Vzhledem k vašemu dotazu nepotřebujete všechny tyto dílčí dotazy. Jsou velmi drahé a zbytečné. Vlastně je to docela šílené. V této části dotazu

    SELECT  a.ID, 
            a.Time, 
            a.SerialNumber, 
            a.Remain_Toner_Black,
            a.Remain_Toner_Cyan,
            a.Remain_Toner_Magenta,
            a.Remain_Toner_Yellow,
            (
                SELECT  COUNT(*)
                FROM    Reports c
                WHERE   c.SerialNumber = a.SerialNumber AND
                        c.ID <= a.ID) AS RowNumber
    FROM    Reports a

vyberete celou tabulku a pro každý řádek spočítáte řádky v této skupině. To je závislý poddotaz. Všechno jen proto, abychom měli nějaké číslo řádku. Pak to uděláte podruhé, abyste mohli spojit tyto dvě dočasné tabulky a získat předchozí řádek. Opravdu není divu, že výkon je hrozný.

Jak tedy přizpůsobit své řešení vašemu dotazu? Místo jedné proměnné, kterou jsem použil k získání předchozího řádku pro Remain_Toner_Black, použijte čtyři pro barvy černá, azurová, purpurová a žlutá. A stačí se připojit ke stolu Tiskaři a zákazníci jako vy. Nezapomeňte na objednávku a máte hotovo.




  1. Snadná správa souborů AWS S3

  2. phpMyAdmin + CentOS 6.0 – Zakázáno

  3. Při instalaci SQL Server Management Studio 2016 nebylo možné určit platnou cílovou složku pro instalaci

  4. Chyba importu databáze phpMyAdmin #1046 - Není vybrána žádná databáze