SQL dotaz na MAX   zodpovězená otázka

SQL, Databáze

Zdravím vespolek,

snažím se snažím, ale už nevím jak dál..

Mám tabulku, v ní záznamy s ID které je jedinečné.

V druhé tabulce mám v prvním sloupci ID z předchozí tabulky a navíc 3 sloupce, s tím, že v jednom je datum.

Potřeboval bych ke každému záznamu tabulky 1 vybrat jeden záznam z tabulky 2,(popřípadě NULL pokud žádný není) s maximálním datem a ostatními údaji které s tímto datumem jsou v řádku.

Jediné co se mi povedlo je buď, více totožných záznamů tabulky 1 a oba záznamy z tabulky 2, nebo slátaninu tabulky 2 (jedna hodnota z řádku 1, druhý sloupec hodnota z řádku 2)

Slátanina:

SELECT TableAll.Number, TableAll.IDNumber, TableAll.DepartmentNoImplementation, MAX(TableChangeStatus.Status)

AS Status, MAX(TableChangeStatus.IDWhoHandedItOver) AS IDWhoHandedItOver, MAX(TableChangeStatus.IDWhomItWasHandedOver)

AS IDWhomItWasHandedOver, MAX(TableChangeStatus.DateChanges) AS DateChanges

FROM TableAll LEFT OUTER JOIN

TableChangeStatus ON TableAll.Number = TableChangeStatus.Number

GROUP BY TableChangeStatus.Number, TableAll.Number, TableAll.IDNumber, TableAll.DepartmentNoImplementation

Oba záznamy:

SELECT TableAll.Number, TableAll.IDNumber, TableAll.DepartmentNoImplementation, TableChangeStatus.Status,

TableChangeStatus.IDWhoHandedItOver, TableChangeStatus.IDWhomItWasHandedOver, TableChangeStatus.DateChanges

FROM TableAll LEFT OUTER JOIN

TableChangeStatus ON TableAll.Number = TableChangeStatus.Number

GROUP BY TableChangeStatus.Number, TableAll.Number, TableAll.IDNumber, TableAll.DepartmentNoImplementation,

TableChangeStatus.DateChanges, TableChangeStatus.IDWhomItWasHandedOver, TableChangeStatus.IDWhoHandedItOver,

TableChangeStatus.Status

Doufám že to někdo pochopí :-(

Pokud nechám z druhé tabulky pouze datum, je vše OK.

Ještě doplním, že je to SQL DB v ASP.NET.

S díky Karel

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Doporučuju nastudovat příkaz PARTITION BY..ten by Vám mohl pomoci

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Udělejte si z tabulky2 select s groupováním podle odkazu do tabulky1 a najděte si agregací MAX odpovídající datum.

Tento dotaz pak jako sub-select najoinujte pomocí left-join do tabulka1.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Díky moc za snahu, bohužel nevím jak na to :-(

Bylo by troufalé Vás požádat o chvíli Vašeho času aby jste mi to přiblížil?

První část jsem udělal, ale nevím jak výsledek propojit znovu s Tabulkou 1.

Zda je výsledek:

SELECT TableAll.Number, MAX(TableChangeStatus.DateChanges) AS MAXDateChanges

FROM TableAll LEFT OUTER JOIN

TableChangeStatus ON TableAll.Number = TableChangeStatus.Number

GROUP BY TableAll.Number

Vybere mi to ke každému záznamu v tabulce TableAll datum z tabulky TableChangeStatus. Další položky (např. Status z tabulky TableChangeStatus a IDNumber z tabulky TableAll) přiřadím asi tím rozšířeným dotazem, který bohužel nevím jak postavit :-(

Jenom pro úplnost, v tabulce TableChangeStatus nemusí být žádný záznam..

S díky za Váš čas Karel Láska

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Vždyť máte napsáno jak to udělat,tak si to řádně přečtěte a také dle toho udělejte.Takto to máte blbě,respektive ne dle popisovaného postupu.Nečekejte,že to za Vás někdo udělá.Nejedná se zas o takovou složitost,abyste to nezvládl

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Není důvod být nepříjemný.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Důležité je zde udělat samostatný subselect. Nemusí pak přemýšlet jaké všechno groupování budete přidávat do výsledku. Například:

select 
        tabulka1.Number, 
        tabulka1.DalsiVlastnost1, 
        tabulka1.DalsiVlastnost2,
        tabulka2grp.MaxDataChanges
    from tabulka1
    left join (
        select Number, MAX(DataChanges) as MaxDataChanges from table2 
        group by Number
    ) tabulka2grp on tabulka2grp.Number = tabulka1.Number
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Díky moc,

posunulo mě to o trochu dál :-)

Povedlo se mi vytvořit stejný dotaz na mojí databázi, vše bylo OK, pouze do chvíle, dokud jsem se nesnažil přidat "dalsivlastnost1" z tabulky 2. Od té chvíle byly vybrány opět oba řádky s rozdílnými vlastnostmi...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zkuste to popsat více,takto to není moc pochopitelné.Respektive co chcete nově přidat

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zdravím, přikládám to, co mělo být asi už v zadání, sipu si popel na hlavu :-)

Tabulka 1

Number Kdo Co

1 Pepa Utrhl výfuk

2 Pavel Píchl pneu

Tabulka 2

Number Kdo Kdy Co

1 Šef 1.1.2012 Objednal výfuk

1 Příjem 3.2.2012 Přijal výfuk na sklad

1 Mechanik 5.2.2012 Namontoval Výfuk

Výsledek

Number Kdo Co Kdo Kdy Co

1 Pepa Utrhl výfuk Mechanik 5.2.2012 Namontoval

2 Pavel Píchl pneu NULL NULL NULL

nahlásit spamnahlásit spam 0 odpovědětodpovědět

A v čem je problém?Vždyt jen přidáte další vlastnosti do selectu:

select 
        tabulka1.Number, 
        tabulka1.DalsiVlastnost1, 
        tabulka1.DalsiVlastnost2,
        tabulka2grp.Vlastnost1,
        tabulka2grp.MaxDataChanges,
        tabulka2grp.Vlastnost2
    from tabulka1
    left join (
        select Number, MAX(DataChanges) as MaxDataChanges from table2 
        group by Number
    ) tabulka2grp on tabulka2grp.Number = tabulka1.Number
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Pokud to udělám přímo dle Vašeho návodu, SQL dotaz řve, že se mu nelíbí, že není tabulka2grp.Vlastnost2 GROUP BY.

Pokud položku přidám "group by Number,Vlastnost2" do vnořenýho selectu, vystupem je řádek 1 3x po sobě jdoucí se všemi položkami druhého seznamu a ne pouze poslední.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Omlouvám se,odeslal jsem kód omylem dříve než jsem ho dopsal:

select 
        tabulka1.Number, 
        tabulka1.DalsiVlastnost1, 
        tabulka1.DalsiVlastnost2,
        tabulka2grp.Vlastnost1,
        tabulka2grp.MaxDataChanges,
        tabulka2grp.Vlastnost2
    from tabulka1
    left join (
        select Number, MAX(DataChanges) as MaxDataChanges,Vlastnost1,Vlastnost2 from table2 
        group by Number
    ) tabulka2grp on tabulka2grp.Number = tabulka1.Number
 
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Je to ten samý případ co jsem popsal o příspěvek výše.

Pokud kód upravím, takto

select 
        tabulka1.Number, 
        tabulka1.DalsiVlastnost1, 
        tabulka1.DalsiVlastnost2,
        tabulka2grp.Vlastnost1,
        tabulka2grp.MaxDataChanges,
        tabulka2grp.Vlastnost2
    from tabulka1
    left join (
        select Number, MAX(DataChanges) as MaxDataChanges,Vlastnost1,Vlastnost2 from table2 
        group by Number,Vlastnost1,Vlastnost2
    ) tabulka2grp on tabulka2grp.Number = tabulka1.Number

tzn. přidám

,Vlastnost1,Vlastnost2

Nevyhodnotí se jeden řádek ale všechny...

Jinak jak jsem psal ráno - viz příspěvek na samém konci, mám to již hotové pomocí podmínek, pouze mě zajímá, zda to nejde řešit ještě jinak.(Jednodušeji)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ten kód je už z principu špatně. Nemůžete přece groupovat položky, které se groupovat nemají. Tím ztratíte požadovanou hodnotu. Groupovat se musí jen a pouze pomocí klíče Number, který rozhoduje o referenci na tabulku1. Groupování podle dalších sloupců zapříčiní více řádků pro stejný Number a tím i zdvojování výsledků, což obvykle znamená nepěkné chyby.

Řešení tohoto "nového" problému je trochu složitější, než jsem popisovat, Pokud totiž chcete získávat i další hodnoty, které nedokážete získat pomocí agregačních funkcí (například MAX), je potřeba udělat minimálně o jeden další sub-select navíc.

Například následující kód nejprve zjistí Id nejvyšších datumů v table2 podle Number sloupce a následně na ně najoinuje všechny ostatní sloupce z této tabulky. Tím máme jistotu, že je pro každý number z této tabulky vybrán jedinný záznam.

Zbytek je už jasný (stejný jako u minulého příkladu).

Btw píšu to z hlavy, takže nevím, jestli jsem neudělal syntaktickou chybu.

select 
        tabulka1.Number, 
        tabulka1.DalsiVlastnost1, 
        tabulka1.DalsiVlastnost2,
        tabulka2grp.MaxDataChanges,
        tabulka2grp.DalsiVlastnost3
    from tabulka1
    left join (
        select tabulka2.* from (
            select 
                    -- zde je dulezity "top 1", díky kterému se bude ignorovat více záznamů se stejným datem pro stejný 'Number'
                    (select top 1 Id from table2 table2src where table2.Number = table2src.Number and MAX(DataChanges) = table2src.DataChanges) as Id 
                from table2 
                group by Number
        ) tabulka2grpMax
        join tabulka2 on tabulka2.Id = tabulka2grpMax.Id
    ) tabulka2grp on tabulka2grp.Number = tabulka1.Number

Jinak doporučuji podívat se na RANKING funkce u SQL Serveru, které dokáží váš problém vyřešit elegantněji. Dovolují totiž číslovat řádky podle skupin a ty pak filtrovat, Takže lze snadněji definovat dotaz, kde z table2 vyberete všechny řádky s nejvyšším DataChanges a zároveň unikátním Number. Odkaz: http://msdn.microsoft.com/en-us/library/...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zdravím, tak předkládám finální verzi...



SELECT     TableAll.Number, TableChangeStatus.DateChanges, TableAll.IDNumber, TableChangeStatus.IDWhomItWasHandedOver, 
                      TableChangeStatus.IDWhoHandedItOver, TableChangeStatus.Status, TableChangeStatus.DateChanges AS MAxDateChange
FROM         TableAll LEFT OUTER JOIN
                      TableChangeStatus ON TableAll.Number = TableChangeStatus.Number
WHERE     (TableChangeStatus.DateChanges =
                          (SELECT     MAX(TableChangeStatus_1.DateChanges) AS MAXDataChanges
                            FROM          TableAll AS TableAll_1 LEFT OUTER JOIN
                                                   TableChangeStatus AS TableChangeStatus_1 ON TableAll.Number = TableChangeStatus_1.Number)) OR 
                      (TableChangeStatus.DateChanges IS NULL)
GROUP BY TableAll.Number, TableAll.IDNumber, TableChangeStatus.IDWhomItWasHandedOver, 
                      TableChangeStatus.IDWhoHandedItOver, TableChangeStatus.Status, TableChangeStatus.DateChanges

Díky moc za pomoc a myslím že nebude trvat dlouho a budu zde zase :-)

S pozdravem Karel

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zdravím,

udělal jsem to znovu a lépe a zdá se že konečně to mám hotové.

Vzal jsem tabulku 2, ke každému jedinečnému číslu z tabulky 1, jsem přiřadil MAX z datumu. Potom jsem přiřadil k tabulce 1 všechny záznamy z tabulky 2 a do podmínky jsem vložil zmíněný select. Dotaz mi už funguje, díky, jen se chci zeptat, zda je tato cesta správná.

(např. nebude li zbytečně zatěžovat DB, atd.)

S díky Láska Karel

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback