• Bucci

    Pravidla soutěže:

    1. Do soutěže je možno vkládat libovolné hádanky, rébusy, šifry k rozluštění či jiné kratší úlohy z oblasti programování, algoritmizace či informačních technologií obecně.
    2. Soutěžní úlohy musejí být koncipovány tak, aby pro jejich úspěšné řešení bylo zapotřebí kreativní myšlení, nikoli jen pouhé znalosti.
    3. Kdo soutěžní úlohu úspěšně vyřeší, má právo zadat další. Neučiní-li tak do 24 hodin od odeslání správné odpovědi, může novou soutěžní úlohu zadat kdokoli jiný.
    4. Nedaří-li se soutěžní úlohu vyřešit, může její zadavatel postupně přidávat nápovědy. Na konci musí zadavatel zveřejnit správné řešení, nebo potvrdit správnost řešení někoho ze soutěžících.
    5. Příjemnou zábavu (a koho to nezajímá, prosíme nerušit).
    • Bucci  

      A první otázka, z oblasti relačních databází (dostal jsem ji kdysi na jednom pracovním pohovoru):

      Mějme následující tabulku:

      COMPANY_ID      P­ARENT_COMPANY_ID       C­OMPANY_NAME

      =============­========================­=========================

      1                _null                    ­eBay Inc.

      2                _null                    ­Google Inc.

      3               1                       e­Bay Europe

      4               1                       e­Bay Asia & Pa­cific

      5               2                       G­oogle Europe

      6               2                       G­oogle Asia & Pa­cific

      7               3                       e­Bay Czech Repu­blic

      8               3                       e­Bay Germany

      9               3                       e­Bay Switzerland

      10              ­4                       e­Bay China

      11              ­4                       e­Bay South Korea

      12              ­4                       e­Bay Japan

      13              ­5                       G­oogle Czech Re­public

      14              ­5                       G­oogle Germany

      15              ­5                       G­oogle Switzer­land

      16              ­6                       G­oogle China

      17              ­6                       G­oogle South Ko­rea

      18              ­6                       G­oogle Japan


      Vypište jediným SQL dotazem všechny národní filiálky všech firem, přičemž u každé bude na stejném rádku vypsána i její nadřízená oblastní pobočka a příslušná globální korporace. Nesmíte použít PL/SQL ani žádné jiné programovací techniky nad rámec prostého čistého SQL.

      (Pozn.: COMPANY_ID 1 a 2 jsou globální korporace, COMPANY_ID 3 – 6 jsou oblastní pobočky, zbytek národní filiálky.)

      • Bucci  

        Jo a tabulka se jmenuje třeba .. COMPANY (jak jinak) :-)

      • Tacmud  

        SELECT fil.company_name, oblglob.compa­ny_name, oblglob.global_com­pany_name FROM company fil JOIN (SELECT obl.company_id, obl.parent_com­pany_id, obl.company_name, glob.company_name global_company_name FROM company obl JOIN (SELECT * FROM company WHERE parent_company_id IS NULL) glob ON obl.parent_com­pany_id = glob.company_id) oblglob ON fil.parent_com­pany_id = oblglob.company_id

        Řekl bych, že něco takovýho. Píšu to z hlavy a nemám sílu to takhle po ránu po sobě kontrolovat, takže tam může být překlep. Tabulku do DB kvůli ověření zakládat nehodlám.

        Dal's to?

        • Bucci  

          jj dal, a použil jsem toto:

          SELECT

          c1.company_name narodni,

          c2.company_name oblastni,

          subs.company_name globalni

          FROM

          company c1

          JOIN company c2 ON (c1.parent_com­pany_id = c2.company_id)

          JOIN (

          SELECT company_id, company_name FROM company WHERE parent_company_id IS NULL

          ) subs ON (c2.parent_com­pany_id = subs.company_id);

          Ale tvoje řešení také funguje, a byls první! Tak můžeš zadat další. :-)

        • Tacmud  

          Chtěl jsem to ráno napsat pomocí více JOINů, ale byl jsem moc ospalej. Pomocí SubJoinů je to taky funkční a o dost názornější (ale asi trochu pomalejší).

          PS.: Pravidla tohoto vlákna jsem si přečet až teď, takže se omlouvám všem, kteří se snažli být první a já jim to vyfouk. Sorry!

          • Tacmud  

            Kdyby vám neseděl pojem subJoin, tak na vysvětlenou: jsem samouk a rád se nechám poučit!

            • Bucci  

              Asi sedí. :-) Znám lepší pojmy, například naňůnout si objekt …

              Akorát, prosím, přede mnou nikdy nepoužívejte slovo „Loader.“ Jsem na něj od jisté doby alergický.

            • MichaelSimek  

              subquery je to asi ofiko nazev

              • Bucci  

                a subjoin je join na subquery :-)

                a having je where po group by :-)))

                a nula je víc než nic :-))))))

                Ach jo. Musím naspecifikovat, co jsem naprogramoval. :-)))))))))))))­))))))))))))

    • wilda81  

      SELECT OP.[PARENT_COM­PANY_ID] AS GK_ID

      ,GK.[COMPANY_NAME] AS GK_NAME

      ,NF.[PARENT_COM­PANY_ID] AS OP_ID

      ,OP.[COMPANY_NAME] AS OP_NAME

      ,NF.[COMPANY_ID]

      ,NF.[COMPANY_NAME]

      FROM [COMPANY] NF

      INNER JOIN [COMPANY] OP ON NF.[PARENT_COM­PANY_ID] = OP.COMPANY_ID

      INNER JOIN [COMPANY] GK ON OP.[PARENT_COM­PANY_ID] = GK.COMPANY_ID

      • RomanH  

        Nechce se mi to studovat podrobne, ale kvuli null tam musis mit left outer, a dale Ti tam chybi vycet Id pro typy OP a GK

        • RomanH  

          Neco ve smyslu

          select

          CN.COMPANY_NAME,

          GK.COMPANY_NAME as Global_Company_Na­me,

          OK.COMPANY_NAME as Oblastni_Compa­ny_Name

          FROM [COMPANY] CN

          left outer join [COMPANY] GK on IsNull(GK.PAREN­T_COMPANY_ID,–1) = CN.COMPANY_ID and GK.PARENT_COM­PANY_ID in (1,2)

          left outer join [COMPANY] OK on IsNull(OK.PAREN­T_COMPANY_ID,–1) = CN.COMPANY_ID and OK.PARENT_COM­PANY_ID in (3,4,5,6)

          No a samo si to muzes orderem setridit dle gusta

          • MichaelSimek  

            proc je tam ten isnull?

            a klidne mohl byt inner, protoze vsechny pobocky maji global i oblastni jmeno ne null

            • RomanH  

              Tak zalezi, jak ma na obecne setem nastaveno chovani. Ja uz si na MS-SQL nekolikrat nabehnul, tak to tam radeji davam preventivne a vim, co to udela. A v te tabulce ma u Parent_Company_Id NULL hodnoty.

        • wilda81  

          Inner jsem použil záměrně abych odfiltroval ty co nemají žádnou op a gk. Pak žádný výčet nepotřebuješ ani když přidáš další op nebo gk.

          • RomanH  

            Ja bral, ze chce vypsat vsechny pobocky.

            • wilda81  

              Já tam četl národní filiálky, tak jsem to bastlil právě bez nich.

              • RomanH  

                jsem se donutil hodit si to do tabulky, mels to dobre

                select

                GK.COMPANY_NAME as Globalni_Compa­ny_Name,

                OK.COMPANY_NAME as Oblastni_Compa­ny_Name,

                CN.COMPANY_NAME as Narodni_Compa­ny_Name

                FROM @COMPANY CN

                inner join @COMPANY OK on OK.COMPANY_ID = CN.PARENT_COM­PANY_ID

                inner join @COMPANY GK on GK.COMPANY_ID = OK.PARENT_COM­PANY_ID

    • MichaelSimek  

      tak kdyz sql tak sql s kterym si moji studenti moc nevedeli rady

      jsou 3 tabulky (zakaznik, zbozi, objednavka)

      a chci vybrat _VSECHNY_ zakazniky a pokud objednali zbozi s vlastnostiX tak datum kdy ho objednali

      pripravil jsem to i s db/datama abyste se tim nemuseli trapit

      vysledek by mel vypadat nejak takto:

      z1 2016–01–01 00:00:00.000

      z2 NULL

      z3 NULL

      declare @zak table (

      id int primary key,

      name varchar(30)

      )

      declare @zbo table (

      id int primary key,

      name varchar(30),

      vlastnostx bit

      )

      declare @obj table (

      zak int ,

      zbo int ,

      datum datetime

      )

      insert into @zak values(1, ‚z1‘)

      insert into @zak values(2, ‚z2‘)

      insert into @zak values(3, ‚z3‘)

      insert into @zbo values(1, ‚v1‘, 1)

      insert into @zbo values(2, ‚v2‘, 0)

      insert into @zbo values(3, ‚v3‘, 0)

      insert into @obj values(1, 1, ‚2016–1–1‘)

      insert into @obj values(1, 2, ‚2016–1–2‘)

      insert into @obj values(2, 2, ‚2016–1–3‘)

      insert into @obj values(2, 3, ‚2016–1–4‘)

      • wilda81  

        jestli to mělo být datum poslední objednávky, tak v MSSQL třeba takto

        SELECT ZAKAZNIK.name, OBJEDNAVKA.datum FROM @zak ZAKAZNIK

        OUTER APPLY

        (

        SELECT TOP 1 * FROM @obj OBJEDNAVKA

        INNER JOIN @zbo ZBOZI ON OBJEDNAVKA.zbo = ZBOZI.id

        WHERE zak = ZAKAZNIK.id AND ZBOZI.vlastnostx = 1

        ORDER BY datum DESC

        ) OBJEDNAVKA

        edit: a nebo pomocí CTE

        • MichaelSimek  

          jde prave i jednoduseji a efektivneji (samorzejme bez pouziti cte atp) jednoduchy dotaz bez poddotazu

          • wilda81  

            menit zadani behem testu je podpasovka „pančeli“ :))

            • MichaelSimek  

              tak to oni v ty dobe neumeli ani cte ani poddotazy takze tak zadani stacilo :D

              • Rorejs74  

                A „case“ umeli ? Pak by to slo prasacky udelat takhle ;-)

                select zz.name,

                case

                when ( zz.id = o.zak ) then o.datum

                else null

                end as „datum“

                from

                #zak zz,

                #obj o,

                #zbo z

                where

                ( o.zbo = z.id ) and

                ( z.vlastnostx = 1 )

                Prepsal jsem si to do Sybasi syntaxe a fakt to vraci to ma ;-)

                z1 Jan 1 2016 12:00AM

                z2 NULL

                z3 NULL

                • MichaelSimek  

                  to sice taky neumeli, ale fuj to je cross join spojenej casem :D

                  jde to pres normalni joiny bez subselektu, a dalsich jakykoliv serepeticek :)

                  • wilda81  

                    SELECT ZAKAZNIK.name, MAX(OBJEDNAVKA­.datum)

                    FROM @zak ZAKAZNIK

                    CROSS JOIN @zbo ZBOZI

                    LEFT JOIN @obj OBJEDNAVKA ON OBJEDNAVKA.zbo = ZBOZI.id AND OBJEDNAVKA.zak = ZAKAZNIK.id AND ZBOZI.vlastnostx = 1

                    GROUP BY ZAKAZNIK.name

                    • MichaelSimek  

                      vy me davate s tema Xjoinama :D, jako jo fungovat to asi bude ale Xjoin by se dal krasne nahradit nejakym rozumynm aby nebyla naracnost selektu takova strasliva :D

                      • Rorejs74  

                        Tak jeste jsem by to slo takhle, ale technicky je to taky vlastne subselect a pripada mi to slozitejsi nez ten primej subselect v select sekci.

                        select zz.name, sel.datum

                        from

                        #zak zz LEFT JOIN ( select o.datum, o.zak from #obj o INNER JOIN #zbo z ON ( z.id = o.zbo ) and z.vlastnostx = 1 ) sel ON sel.zak = zz.id

                        • MichaelSimek  

                          tohle je asi nejhezci co jsem tu videl, a rekl bych ze srovnatelny s mojim puvodnim resenim kdy proste misto subselektu jsou 1 join…rychlostne budou asi srovnatelny zalezi na db…

                          ten kde si mel ten case tak by se nejdriv probehl crossjoin zz se vsema objednavko-zbozima a ten by se pak filtroval, takze narocnosti si myslim uplne jinde nez tohle reseni

                          takze dle soudu zadavatele si vyhral a muzes davat dalsi :D

                          • wilda81  

                            nerikalo se bez vnorenych dotazu? ;)

                            • MichaelSimek  

                              no je fakt ze sem to zapomel napsat v zadani…a nechtel jsem aby nekdo chytrejsi prisel a rekl ze tohle by stejne bylo stejne rychly jako to reseni bez subquery :D

                              • wilda81  

                                Jasne.

                                Jinak k rychlosti a vykonu. Podle exekucnihoi planu je:

                                • reseni s outer apply cca 2× narocnejsi
                                • reseni s CTE uplne stejne
                          • Rorejs74  

                            Tak ja jsem stara skola, takze bych tam automaticky prastil ten subselect a pak to pripadne doladil podle optimalizatoru. Pripadne si hodil seznam tech zakazniku co to objednali predem do nejakyho #tempu.

                            Ale donutil jsi me se podivat do navodu na syntaxi JOINU a uznavam, ze tohle je asi prvni pripad na kterou jsem narazil, kde by se musel pouzit primo JOIN ( kdybych fakt nechtel ten subselect ) a nejde to ekvivalentne rozepsat na = a * tak jak to pisu normalne ;-)

      • Rorejs74  

        Sybase pouziva trosku jinou syntaxi, ale zkusim to pro vlastnostx=1.

        declare @INT_vlastnost integer

        select @INT_vlastnost = 1

        select zz.name,

        ( select o.datum

        from @zbo z,

        @obj o

        where ( z.vlastnostx = @INT_vlastnost ) and

        ( o.zbo = z.id ) and

        ( o.zak = zz.id ) )

        from @zak zz

        samozrejme tohle by fungoval ojen za predpokladu ze to zbozi objednal jen jednou, pokud vickrat, tak by sis musel rict, zda te zajma jen treba prvni nebo posledni datum, pripadne zda se pak ten zakaznik v tom listu ma objevit vickrat ( pokazde s datem objednani ).

        • MichaelSimek  

          ale to ti projde jako inner join a nevybere to vsechny zakazniky ne? ale jenom toho co si vlastnostx objednal

          • Rorejs74  

            Nee, selectne to vsechny zaznamy z tabulky zak a jen to k nim dotahne datum objednavky z tabulek zbo a obj

            • MichaelSimek  

              jo jasne uz to vidim, asi jo, nevim jak moc sybase to optimalizuje a joinuje…u jinych by to bylo ne uplne pekny reseni jako vetsina reseni s korelacnima poddotazama

              • Rorejs74  

                Samozrejme zalezi jak by to bylo indexovany a jakej je ocekavanej objem dat v jednotlivych tabulkach.

                Taky by to asi slo jen takhle :

                select zz.name, o.datum

                from @zak zz,

                @obj o,

                @zbo z

                where ( o.zak *= zz.id ) and

                ( z.id = o.zbo ) and

                ( z.vlastnostx = @INT_vlastnost )

                • MichaelSimek  

                  jak rikam sybase neznam, ale tohle bych rekl ze opravdu projde spatne jelikoz andy budou vyzovat aby vlasnotx byla 1 i u zakazniku kteri treba neamji nic objednano…nehlede na to ze zak*=id je predpokladam „leftjoin“

      • lukas aka mitro  

        Ty jsi jako prvni spravne uhodl predchozi hadanku?:)

      • Bucci  

        Asi takto:

        SELECT

        zak.name,

        obj.datum

        FROM zak

        LEFT JOIN obj ON (zak.id = obj.zak)

        JOIN (

        SELECT id, name FROM zbo WHERE vlastnostx = true

        ) subs ON (obj.zbo = subs.id);

      • pepino  

        A to nerozumíš věte Facce od Almase?

    • hekynen  

      Takové chujoviny řeším v práci „dnes a denně“. Ještě se s tím jebat na bike fóru? Dejte pokoj… ;-)

      CREATE PROCEDURE dbo.uspBikeForum

      AS

      BEGIN

      SET NOCOUNT ON

      SELECT ‚NEBUDU TO DĚLAT! NÉÉÉ!!‘

      END

      GO

      EXEC dbo.uspBikeForum

    • Bucci  

      Tak kurník zadává někdo?

    • c0d3r  

      tak ja davam dalsi … pro zmenu z SQL (Oracle) oblasti :)

      Mame tabulku TABLE:

      cat_id | sub_cat_id | date


      2 | 1 | 1/2/2015

      2 | 1 | 2/2/2015

      2 | 1 | 3/2/2015

      2 | 1 | 6/2/2015

      2 | 1 | 7/2/2015

      2 | 3 | 1/2/2015

      2 | 3 | 30/3/2015

      2 | 3 | 31/3/2015

      2 | 3 | 1/4/2015

      2 | 3 | 2/4/2015

      a pozadovany vystup je (cili chceme videt agregovany vypis rozmezi dat pres categorii a sub categorii):

      cat_id | sub_cat_id | start_date | end_date


      2 | 1 | 1/2/2015 | 3/2/2015

      2 | 1 | 6/2/2015 | 7/2/2015

      2 | 3 | 1/2/2015 | 1/2/2015

      2 | 3 | 30/3/2015 | 2/4/2015

      bez pouziti PL/SQL – date to? :)

      • Rorejs74  

        A na zaklade ceho roztrhnes ve vysledku ty kategorie jeste na dalsi dva radky ?

        Podle zadani by z toho melo podle mne vypadnou tohle :

        2 1 2015–02–01 00:00:00.000 2015–02–07 00:00:00.000

        2 3 2015–02–01 00:00:00.000 2015–04–02 00:00:00.000

        • Rorejs74  

          Ted na to koukam podle dat a ze by to bylo za obdobi, kdy na sebe ty dny navazujou ?

          • Rorejs74  

            Jestli je to tak, tak pak by to mohlo vypadat takhle ( ale je to teda dost desny, pres #temp tabulku by to slo podstatne lip ) :

            select cat_id,

            sub_cat,

            ( select min( date )

            from #temp st

            where ( st.cat_id = t.cat_id ) and

            ( st.sub_cat = t.sub_cat ) and

            ( st.date >= t.date ) ) as „min_date“,

            isnull(

            ( select max( date )

            from #temp st

            where ( st.cat_id = t.cat_id ) and

            ( st.sub_cat = t.sub_cat ) and

            ( st.date >= t.date ) and

            ( not( exists( select 1

            from #temp sst

            where ( sst.cat_id = st.cat_id ) and

            ( sst.sub_cat = st.sub_cat ) and

            ( sst.date = dateadd( day, 1, st.date ) ) ) ) ) and

            ( st.date < ( select min( sst.date )

            from #temp sst

            where ( sst.cat_id = st.cat_id ) and

            ( sst.sub_cat = st.sub_cat ) and

            ( sst.date > dateadd( day, 1, st.date ) ) ) ) ),

            ( select max( date )

            from #temp st

            where ( st.cat_id = t.cat_id ) and

            ( st.sub_cat = t.sub_cat ) ) ) as „max_date“

            from #temp t

            where ( not( exists( select 1

            from #temp st

            where ( st.cat_id = t.cat_id ) and

            ( st.sub_cat = t.sub_cat ) and

            ( st.date = dateadd( day, –1, t.date ) ) ) ) )

            • c0d3r  

              silena query :) z optimalizacniho hlediska sebevrazda nad obrovskyma tabulkama.. zkus to znovu a pouzit analyticke funkce :)

              • c0d3r  

                navic jsem ted testoval Tvoji query a vubec nefunguje pod oraclem …

                • MichaelSimek  

                  v mssql ta jeho funguje

                  v ty moji me tam chybi where na par mistech :D

                  • c0d3r  

                    vsichni jste tu mrkvosousti? :D

                    • Rorejs74  

                      Ja to honim na Sybase a pomohl bych si #temp tabulkou.

                      Mam zkusenosti s tabulkam kde jsou stamiliony zaznamu ( financni sektor ) tak vim co je to optimalizace ;-)

                      • Rorejs74  

                        Treba takhle :

                        create table #temp_dat(

                        cat_id integer,

                        sub_cat integer,

                        date datetime,

                        FLG_min integer,

                        FLG_max integer )


                        insert into #temp_dat

                        select cat_id,

                        sub_cat,

                        date,

                        0,

                        0

                        from #temp


                        update #temp_dat

                        set FLG_min = 1

                        from #temp_dat t

                        where ( not( exists( select 1

                        from #temp st

                        where ( st.cat_id = t.cat_id ) and

                        ( st.sub_cat = t.sub_cat ) and

                        ( st.date = dateadd( day, –1, t.date ) ) ) ) )


                        update #temp_dat

                        set FLG_max = 1

                        from #temp_dat t

                        where ( not( exists( select 1

                        from #temp st

                        where ( st.cat_id = t.cat_id ) and

                        ( st.sub_cat = t.sub_cat ) and

                        ( st.date = dateadd( day, 1, t.date ) ) ) ) )


                        select t.cat_id,

                        t.sub_cat,

                        t.date as „min_date“,

                        ( select min( st.date )

                        from #temp_dat st

                        where ( st.cat_id = t.cat_id ) and

                        ( st.sub_cat = t.sub_cat ) and

                        ( st.date >= t.date ) and

                        ( st.FLG_max = 1 ) ) as „max_date“

                        from #temp_dat t

                        where ( t.FLG_min = 1 )

                        • c0d3r  

                          hh Sybase nemam kde otestovat..a jednim dotazem? v Sybase nejsou analyticke fce?

                          • Rorejs74  

                            Myslim ze tohle umi jen ten Sybase IQ ( datovej sklad ), ale ja si vystacim s tim co mam, zase aspon to mam vic pod kontrolou z hlediska optimalizace a zamykani … vetsinou se potrebuju vyhnout treba worktable, protoze to uz pak nejde pustit na read uncommitted isolation level.

                            • c0d3r  

                              jj reseni jsi nasel a to je hlavni :) .. nejdriv se resi to aby se naslo reseni a pak se resi to, jak moc je na hovno :D

      • MichaelSimek  

        select cat_id, sub_cat_id, tt.date, ttt.date from

        tab t join (

        select * from tab t1 where not exists (select * from tab t2 and datediff(day, t1.date, t2.date)=1 and t1.cat_id = t2.cat_id and t1.sub_cat_id = t2.sub_cat_id)

        ) tt on t.cat_id = tt.cat_id and t.sub_cat_id = tt.sub_cat_id

        join (

        select * from tab t1 where not exists (select * from tab t2 and datediff(day, t1.date, t2.date)=-1 and t1.cat_id = t2.cat_id and t1.sub_cat_id = t2.sub_cat_id)

        ) ttt on t.cat_id = ttt.cat_id and t.sub_cat_id = ttt.sub_cat_id

        nevim jaka je fce v oraklu pro datediff, ale asi tam neco takoveho bude

        • c0d3r  

          ahoj, Tvoje query mi moc neslape i kdyz jsem ji zkousel prepsat do Oracle.. testovali jste ji nekde? nebo pisete naslepo?

          ps: nemas uplne dobre zavorky !!

          • MichaelSimek  

            otestuju az bude cas, vim ze me tam neco chybi, psal jsem to rano pri snidani naslepo :) ale jsem si jisty ze to pofrci! :D

    • Rorejs74  

      Jeste bych zreinkarnoval to predchozi zadani, ale jinou ( old school ;-) ) variantu reseni ( viz nize )

      jsou 3 tabulky (zakaznik, zbozi, objednavka)

      a chci vybrat _VSECHNY_ zakazniky a pokud objednali zbozi s vlastnostiX tak datum kdy ho objednali

      pripravil jsem to i s db/datama abyste se tim nemuseli trapit

      vysledek by mel vypadat nejak takto:

      z1 2016–01–01 00:00:00.000

      z2 NULL

      z3 NULL

      declare @zak table (

      id int primary key,

      name varchar(30)

      )

      declare @zbo table (

      id int primary key,

      name varchar(30),

      vlastnostx bit

      )

      declare @obj table (

      zak int ,

      zbo int ,

      datum datetime

      )

      insert into @zak values(1, ‚z1‘)

      insert into @zak values(2, ‚z2‘)

      insert into @zak values(3, ‚z3‘)

      insert into @zbo values(1, ‚v1‘, 1)

      insert into @zbo values(2, ‚v2‘, 0)

      insert into @zbo values(3, ‚v3‘, 0)

      insert into @obj values(1, 1, ‚2016–1–1‘)

      insert into @obj values(1, 2, ‚2016–1–2‘)

      insert into @obj values(2, 2, ‚2016–1–3‘)

      insert into @obj values(2, 3, ‚2016–1–4‘)

      K tomu upresneni :

      • nesmi se pouzit subselect v sekci „SELECT“
      • nesmi se pouzit nic jinyho nez primej JOIN ( zadnej LEFT, RIGHT, OUTER … a dalsi novinky ;-) )
      • nesmi se pouzit GROUP BY
      • c0d3r  

        lol to zni jak zadani ze skoly :D

      • RomanH  

        Pomoci unionu

        select Z.Name, O.Datum

        from @Zak Z

        join @obj o on O.zak = z.id

        join @zbo b on b.id = o.zbo and b.vlastnostx = 1

        union select Z.Name,Null from @Zak Z

        akorat teda u te objednavky se je potreba rozhodnout, zda brat napr. posledni, napr. TOP s Orderem, a nebo (pokud chci konkretni vysledek dle zadani a vstupnich dat :

        select Z.Name, O.Datum

        from @Zak Z

        join @obj o on O.zak = z.id

        join @zbo b on b.id = o.zbo and b.vlastnostx = 1

        union select Z.Name,case when Z.Id = 1 then ‚2016–1–1‘ else null end from @Zak Z

        • Rorejs74  

          Je to dobra cesta, ale ten prvni select Ti toho zakaznika „z1“ vrati 2× ( jednou s null a jednou s 01–01–2016 )

          Ten druhej zase neni moc obecnej a navic toho „z1“ vrati taky 2× ;-)

          • RomanH  

            ad ten druhej : na microsoftu nee, musel bych tam dat union all, jinak stejne zaznamy vynechava

            • Rorejs74  

              Aha, no i tak to ale asi neni idealni, zmeni se data a budes muset menit kod ;-)

            • RomanH  

              Jinak by to slo obecne takto, jestli to teda neni proti Tvymu zadani :

              select Z.Name, O.Datum

              from @Zak Z

              join @obj o on O.zak = z.id

              join @zbo b on b.id = o.zbo and b.vlastnostx = 1

              union

              select Z.Name, Null

              from @Zak Z

              where Z.Id not in (select O.zak from @Obj O

              join @zbo b on b.id = o.zbo and b.vlastnostx = 1

              )

              • Rorejs74  

                No ja bych to napsal trochu jinak, ale rekl bych ze to Tvoje reseni splnuje zadani ;-)

                select zz.name, o.datum

                from

                #zak zz,

                #obj o,

                #zbo z

                where

                ( o.zak = zz.id ) and

                ( o.zbo = z.id ) and

                ( z.vlastnostx = 1 )

                union

                select zz.name, null

                from

                #zak zz

                where ( not( exists( select 1

                from #obj o,

                #zbo z

                where ( o.zak = zz.id ) and

                ( o.zbo = z.id ) and

                ( z.vlastnostx = 1 ) ) ) )

      • wilda81  

        EXEC [hekynen].[dbo]­.[uspBikeForum]

    • jan.pernik  

      Zadání řešení: 2 formulářová číselná pole. Před uložením zkontrolovat, že hodnota v nich uložená je shodná. Občas je však nutné zadat hodnotu jinou. Jak poznám kdy to povolit – nooo to se tak nedá říct.

      Jak budete postupovat?

      • c0d3r  

        if ( (input.a eq input.b) || (rand(1,20) eq 1) )

        obcas to bude brat i jinou hodnotu :D .. pripadne se muze zvysit pravdepodobnost obcasnosti snizenim intervalu nahodne vygenerovaneho cisla :D

      • hekynen  

        „Hodnota v polích není stejná! Přesto pokračovat?“

        Ano x Ne x VyserSiOkoDebile.

        ;-)

    • look_as1  

      Tak neco programatorskeho:

      • unikatne setridit velky soubor cisel od 1 do milionu
      • velky znamena desitky milionu zaznamu
      • unikatne znamena bez opakujicich se cisel

      Vyhrava nejrychlejsi algoritmus.

      • lukas aka mitro  

        quicksort parallelne?

      • Rakosnik  

        for int i: vstupni_soubor

        pole[i] = true

        for (i = 1, i<1000000)

        if (pole[i])

        vysledek.add(i)

        • look_as1  

          Tak muzes zadavat dalsi :-)

          Optimalizovana implementace treba v C jepotom krasna prace :-)

          • Rakosnik  

            Pokud chce nekdo jiny zadat jeste dnes, muze. Jinak zkusim do zitrka neco vymyslet:)

      • lukas aka mitro  

        vstup; % zadani pole

        idx = 1:1e+6;

        res = zeros(1,1e+6);

        res(vstup) = vstup([idx]);

      • lukas aka mitro  

        Hmm…hezky zprasene zaznamy, kdyz je tam vetsina (desitky milionu, vs unikatni poradi 1 az milion) zaznamu prazdnych…

      • Vita P.  

        Snad nevadí, že nejsem programátor. Software je pro slečinky, tvrdí chlapi dělají hardware a jako správní masochisti píšou ve VHDL:) Když se vybodneme na procesor a natlačíme to do hradlového pole, tak to jde za jeden ťik hodin:)

        package

        type PortArray is array (0 to data_length) of std_logic_vec­tor(19 downto 0);

        end package;

        entity sort is

        port(

        clk : in std_logic ;

        reset : in std_logic ;

        vstup : in PortArray;

        vystup : out std_logic_vec­tor(7 downto 0)

        );

        end sort;

        architecture behavioural of sort is

        type matrix is array (0 to data_length) of std_logic_vector (19 downto 0);

        signal mat_temp : matrix := (others ⇒ (others ⇒ ‚0‘));

        begin

        mat_temp <= vstup;

        process(clk,rstn)

        variable temp : std_logic_vec­tor(7 downto 0):=(others =>‚0‘);

        variable temp_mat : matrix := (others ⇒ „00000000“);

        begin

        if(reset = ‚0‘) then

        temp_mat := (others ⇒ (others⇒ ‚0‘));

        temp := (others =>‚0‘);

        out_pixel <= (others =>‚0‘);

        elsif (rising_edge(clk)) then

        temp_mat := mat_temp;

        loop1:for i in 0 to data_length loop

        loop2: for j in 0 to data_length loop

        if(temp_mat(i) > temp_mat(j)) then

        temp := temp_mat(i);

        temp_mat(j) := temp_mat(i);

        temp_mat(i) := temp;

        end if;

        end loop loop2;

        end loop loop1;

        vystup <= temp_mat(1);

        end if;

        end process;

        end behavioural;

    • Bucci  

      Tak já něco zadám:

      Mějme tabulku MESTA o následujících sloupcích:

      id NUMBER(10, 0)

      nazev VARCHAR2(100)

      Dále mějme tabulku CESTY o následujících sloupcích:

      id_start NUMBER(10,0)

      id_cil NUMBER(10,0)

      vzdalenost NUMBER(8,4)

      Napište nad touto datovou strukturou v PL/SQL Dijkstrův algoritmus pro nalezení nejkratší cesty z města A do města B.

      Pozn.: Všechny cesty v tabulce CESTY jsou považovány za obousměrné, tj. co vede z A do B, vede i z B do A.

      • c0d3r  

        dobry .. pozdravuj ve skole ;-)

        /**** schema */

        CREATE TABLE points

        ( id number(5)

        , name varchar2(30)

        );

        CREATE TABLE connections

        ( from_id number(5)

        , to_id number(5)

        , distance number(5)

        );

        /**** data */

        INSERT INTO points VALUES(1, ‚A‘);

        INSERT INTO points VALUES(2, ‚B‘);

        INSERT INTO points VALUES(3, ‚C‘);

        INSERT INTO points VALUES(4, ‚D‘);

        INSERT INTO points VALUES(5, ‚E‘);

        INSERT INTO connections VALUES(1,2,3);

        INSERT INTO connections VALUES(1,3,6);

        INSERT INTO connections VALUES(2,4,5);

        INSERT INTO connections VALUES(2,5,2);

        INSERT INTO connections VALUES(3,4,1);

        INSERT INTO connections VALUES(3,5,2);

        /**** base view */

        CREATE OR REPLACE VIEW point_connections AS

        SELECT from_point.name as from_point

        , to_point.name as to_point

        , conn.distance as distance

        --

        FROM points from_point

        , connections conn

        , points to_point

        --

        WHERE 1=1

        AND conn.from_id = from_point.id

        AND conn.to_id = to_point.id

        /**** get cost of route from A point */

        SELECT level as number_of_transfers

        , sys_connect_by_pat­h(distance,‚+‘) as route_cost

        , CONNECT_BY_ROOT from_point||sys_con­nect_by_path(to_po­int,‚/‘) as route

        FROM point_connections pc

        CONNECT BY NOCYCLE PRIOR to_point = from_point

        START WITH from_point = ‚A‘

        /**** PL/SQL function to calc route_cost */

        CREATE OR REPLACE FUNCTION evaluate_string(

        p_string in varchar2

        ) RETURN number

        IS

        l_result NUMBER;

        BEGIN

        EXECUTE IMMEDIATE ‚select '||p_string||‘ from dual' INTO l_result;

        RETURN l_result;

        END evaluate_string;

        /**** final query (A;D) */

        SELECT graph.*

        , evaluate_strin­g(graph.route_cos­t) distance

        FROM (SELECT level as number_of_transfers

        , sys_connect_by_pat­h(distance,‚+‘) as route_cost

        , CONNECT_BY_ROOT from_point||sys_con­nect_by_path(to_po­int,‚/‘) as route

        FROM point_connections pc

        WHERE 1=1

        CONNECT BY NOCYCLE PRIOR to_point = from_point

        START WITH from_point = ‚A‘ – start

        ) graph

        WHERE 1=1

        AND regexp_like(rou­te,‚D‘) – dest

        ORDER BY distance

      • MichaelSimek  

        nesmite ty zadani delat tak ze reseni je na dlouho, pak se to nikomu nebude chtit delat…az na c0d3ra :D

        • lukas aka mitro  

          V necem normalnim tohle vyresis na par radku…ale kdyz jeste definuje jakym jazykem to ma byt, tak smula no..:)

    • MichaelSimek  

      vytvorit fci (ja to delal v JS a tam to slo normalne, nevim jak jiny jazyky) vstup bude uzivateluv vyber cisla mezi 0–2 a druhy parametr bude nahodny cislo 0–2 (je to kamen nuzky papir)…vystup bude treba 0 kdyz je remiza (kamen=kamen), 1 kdyz vyhraje uzivatel, 2 kdyz vyhraje pocitac (nahodne cislo)

      ale! nesmi se pouzivat zadny IF ani podminkovy operator ani switch ci neco na ten zpusob,

      TLDR: bez podminek vyresit kamen nuzky papir

    • Rorejs74  

      Tak tady jeden jednoduchej, ale da se v nem taky pekne zamotat.

      Jednoduchej select na SQL, kterej pro vstupni promenou typu datetime vrati datum poslednihe dne ve stejnem mesici a roce.

      Priklad

      declare @DAT_vstup datetime

      select @DAT_vstup = „03–03–2015“

      select abrakadabra( @DAT_vstup ) as „DAT_vysledek“


      vrati to „03–31–2015“

      • RomanH  

        Prvni den nasledujiciho mesice – 1. Jsem v saline, nechce se mi t tukat na mobilu :-)

        • wilda81  

          +1

        • Rorejs74  

          JJ, podstatou hadanky bylo jit pres ten nasledujici mesic, zazil jsem uz i kolegy co tam psali vycty mesicu a poctu dni v nich ;-)

          • Tacmud  

            Já jsem v jedné slabé chvíly (velmi slabé) psal v PHP funkci která má vstupní parametr datum a vrací datum prvního dne v roce! Po půl dne programování a desítek řádků kódu jsem si uvědomil, že stačí vzít ze vstupního parametru rok a měsíc i den se rovná jedničce!!!

            Do dnes si to pamatuju jako megafail.

            • Deathwing  

              pul dne a desitky radku kodu? neni to nejak moc

              vzdyt staci v cyklu odecitat 1den tak dlouho dokud se ti rok nezmensi o 1 a pak pricist zpatky 1 den to je tak na 4 radky (aspon podle Javy)

              leda bys pri ty slaby chvilce chtel zapojit i optimalizaci :D

              • Tacmud  

                Nechápu, proč odčítat cyklicky jedničku, kedž stačí předpokládat, že první den v roce bude 1. ledna! Já měl ale tak slabou chvilku, že jsem se pokoušel vymyslet ověření zda tomu tak opravdu je! Co kdyby ten deklarovaný rok začínal třeba 2. ledna, nebo 3. ledna, …!!!

                • Deathwing  

                  to za predpokladu ze si neuvedomis ze prvni den v roce je prvniho ledna (samozrejme ze spravny reseni je vzit rok a pridat k nemu 1.1)

                  • Tacmud  

                    zase vzít z datumu rok, přidat k němu ‚1.1.‘ je vlastně práce s txt řetězci a to mě moc připomíná čsštinu na základce!!! Radši to budu počítat nějakými matematickými metodami (i kdyby ten program běžel dvakrát déle)! ;-)

            • wilda81  

              Den je nuda. Vetsi sranda je s cislovanim tydnu.

              • hekynen  

                jj, týdny jsou supr. Zejména když ti rok (1.1.) může „začínat“ 53. týdnem… :-DD

                • Tacmud  

                  apropo… jak je to s týdny letos? Papírové kalendáře se do těch digitálních liší o jeden týden! Teda alespoň podle toho co jsem si všimnul já!

      • c0d3r  

        SELECT last_day(‚datum‘) FROM dual

        • Rorejs74  

          Takovy novoty tu nevedu a taky to vubec nevypada zajimave ;-)

          Pekne po staru se to da napsat takhle :

          select dateadd( day, –1, dateadd( month, 1, convert( datetime, convert( varchar( 2 ), datepart( month, @DAT_vstup ) ) + „-01-“ + convert( varchar( 4 ), datepart( year, @DAT_vstup ) ) ) ) ) as „DAT_vysledek“

          • wilda81  

            Konvert/cast je zlo. Zkus to bez nich ;)

            • Rorejs74  

              convert je v pohode kdyz ho nepouzijes v where sekci kde s nim miva problem optimalizator ;-)

              • wilda81  

                ale neni v pohode, kdyz mas za mesic louskat k cemu ten kousek kodu je :-)

                osobne bych to napsal radeji takto:

                SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, @DAT_vstup) + 1, 0) – 1

                • Rorejs74  

                  Jak rika klasik. „Bylo to slozity to vymyslet, tak nemuze bejt jednoduchy to pochopit“ ;-)

                  Ale teda ten tvuj zapis nechapu, i kdybych pripustil ze muzu na promennou typu datetime pouzit –1 abych se dostal o den zpet, tak do funkce dateadd by melo snad vstupovat datum.

                  Minimalne na Sybase je to deklarovano jako :

                  DATEADD ( date-part, numeric-expression, date-expression )

                  • MichaelSimek  

                    datetime ± 1 by den nikdy neodecetl

                    date ± 1 ano

                    a jako parametr by asi predat sel jelikoz date je porad jenom cislo normalni

                    ale spatne to je stejne protoze predava pocet mesicu jako to cislo a ne pocet dnu

                    • wilda81  

                      V MSSQL to je presne naopak. Zatimco datetime ± 1 bez problemu funguje a odecita/pricita den, tak date (a datetime2) ± 1 zhavaruje na chybe, ze neni kompatibilni s typem int. K datetime muzes v pohode pricitat i destinna cisla tj. 0.5 = 12hod apod.

      • Bucci  

        Co takhle takhle:

        SELECT TO_CHAR((TRUN­C(datum, ‚MM‘) + INTERVAL ‚1‘ MONTH) – INTERVAL ‚1‘ DAY, ‚YYYY-MM-DD HH24:MI:SS‘) FROM dual;

    • Bucci  

      Tak já něco zadám:

      Mějme starou známou hierarchickou tabulku COMPANY (viz. 2. příspěvek tohoto vlákna), její sloupce jsou:

      COMPANY_ID NUMBER(10,0),

      PARENT_COMPANY_ID NUMBER(10,0),

      COMPANY_NAME VARCHAR2(100)

      Dále uvažujme, že úrovní v hierarchi může být libovolně mnoho, nikoli jen 3 jako v předešlém případě.

      A mějme jedno náhodné COMPANY_ID z této tabulky (nazvěme jej třeba „VZOREK“), o němž nevíme, ve které úrovni hierarchie se nachází. Může to být stejně dobře root jako list.

      Úkol zní: Bez použití PL/SQL vypište VZOREK a kompletní strom jeho potomků. (Na jejich pořadí nezáleží.)

      • c0d3r  

        hhh pretty easy :) CONNECT BY … a vyrid ucitelce at si vymysli neco tezsiho :D

        WITH t(c_id, pc_id, c_name) AS (

        SELECT 1,1,‚C11‘ FROM Dual

        UNION ALL

        SELECT 2,1,‚C21‘ FROM Dual

        UNION ALL

        SELECT 3,1,‚C31‘ FROM Dual

        UNION ALL

        SELECT 4,3,‚C43‘ FROM Dual

        UNION ALL

        SELECT 5,4,‚C54‘ FROM Dual

        UNION ALL

        SELECT 6,2,‚C62‘ FROM Dual

        UNION ALL

        SELECT 7,3,‚C73‘ FROM Dual

        UNION ALL

        SELECT 8,7,‚C87‘ FROM Dual

        )

        SELECT c_id, pc_id, c_name, level

        FROM t

        WHERE 1=1

        START WITH c_id = 3 – dosadte ID pro ktere chcete najit strom

        CONNECT BY nocycle PRIOR c_id = pc_id

        ORDER BY level

        • Bucci  

          Jasně: Ale takhle vypadá rekurzivní řešení, použitelné i pro obrovské databáze /sta milionů řádků/ a zejména tam, kde je potřeba netriviálním způsobem získávat potřebný seznam „VZORKŮ“ v témže dotazu.

          WITH t1(company_id, company_name, parent_company_id) AS (

          SELECT /*+ parallel */

          company_id,

          company_name,

          null parent_company_id

          FROM

          company

          WHERE company_id = <VZOREK>

          UNION ALL

          SELECT /*+ parallel */

          t2.company_id,

          t2.company_name,

          t2.parent_com­pany_id

          FROM

          company t2

          JOIN t1 ON (t2.parent_com­pany_id = t1.company_id)

          )

          SELECT /*+ parallel */

          *

          FROM t1;

    • Bucci  

      Tak schválně:

      Mějme v Oracle databázi tabulku TABULKA a v ní sloupec DATUM typu DATE (prosté Oracle date, bez zóny). Uvažujme, že toto datum je platné pro zónu ‚Europe/Prague‘.

      Úkol zní: Překonvertujte DATUM do zóny ‚UTC‘ a výsledek vraťte jako UNIXový timestamp v sekundách. Použít smíte pouze SQL bez subselectu a operace musí být bezpečná (nikde v průběhu výpočtu nesmí vzniknout floating point, taktéž žádný TRUNC a podobné funkce nechci vidět).

      • MichaelSimek  

        date nebo datetime? nebo oracle ma jenom date a to ma v sobe time?

        • Bucci  

          Ano. Oraclí typ DATE je datum a čas bez zóny.

          Pak je ještě typ TIMESTAMP, který obsahuje i zónu.

      • Rorejs74  

        A co takhle jednoduse :

        select datediff( second, „01–01–1970“, DATUM )

        from TABULKA

        Pro kontrolu jsem pouzil :

        declare @DAT_value datetime

        select @DAT_value = „09–09–2001 01:46:40“

        select datediff( second, „01–01–1970“, @DAT_value )

        Vraci to : 1000000000

        EDIT : Jo aha, jeste je tam posun casu.

        • Rorejs74  

          Tak pak bych pouzil dateadd, Sybase to bez namitek vezme i nad promennou typu date :

          declare @DAT_value date

          select @DAT_value = „03–03–2016“

          select datediff( second, „01–01–1970“, dateadd( hour, –1, @DAT_value ) )

          • Rorejs74  

            Pripadne si vlastne tech 3600 muzes odecist i konstantou, predpokladam ze letni cas tam asi neni potreba resit.

      • Bucci  

        Tady je kdyžtak moje Oraclí řešení. Moc efektivní není, ale zadání splňuje, zejména co do té bezpečnosti:

        SELECT

        (EXTRACT(DAY FROM (CAST(FROM_TZ(CAS­T(datum AS TIMESTAMP), ‚Europe/Prague‘) AT TIME ZONE ‚UTC‘ AS TIMESTAMP)) – (TO_TIMESTAMP(‚01–01–1970 00:00:00‘, ‚DD-MM-YYYY HH24:MI:SS‘))) * 86400) + (EXTRACT(HOUR FROM (CAST(FROM_TZ(CAS­T(datum AS TIMESTAMP), ‚Europe/Prague‘) AT TIME ZONE ‚UTC‘ AS TIMESTAMP)) – (TO_TIMESTAMP(‚01–01–1970 00:00:00‘, ‚DD-MM-YYYY HH24:MI:SS‘))) * 3600) + (EXTRACT(MINUTE FROM (CAST(FROM_TZ(CAS­T(datum AS TIMESTAMP), ‚Europe/Prague‘) AT TIME ZONE ‚UTC‘ AS TIMESTAMP)) – (TO_TIMESTAMP(‚01–01–1970 00:00:00‘, ‚DD-MM-YYYY HH24:MI:SS‘))) * 60) + (EXTRACT(SECOND FROM (CAST(FROM_TZ(CAS­T(datum AS TIMESTAMP), ‚Europe/Prague‘) AT TIME ZONE ‚UTC‘ AS TIMESTAMP)) – (TO_TIMESTAMP(‚01–01–1970 00:00:00‘, ‚DD-MM-YYYY HH24:MI:SS‘)))) utc_timestamp

        FROM tabulka;

        • Bucci  

          A elegantnější řešení téhož:

          SELECT TO_NUMBER * 86400 – (EXTRACT(TIME­ZONE_HOUR FROM SYSTIMESTAMP) * 3600), „999999999999999“) AS utc_timestamp

          FROM tabulka

          :-)

          • Bucci  

            BESTIE VYKURVENÁ!!!!! rozmrví ten kód :-(

            SELECT TO NUMBER ( ( datum – TO DATE(‚01–01–1970 00:00:00‘, ‚DD-MM-YYYY HH24:MI:SS‘ ) ) * 86400 – (EXTRACT(TIME­ZONE_HOUR FROM SYSTIMESTAMP) * 3600), ‚999999999999999‘) AS utc_timestamp

            FROM tabulka

    • c0d3r  

      tak mam tady dalsi kvestik pro sikovnejsi hlavicky … Oracle PL/SQL

      tady je procedura ktera ma aktualizovat IRR u smluv, ktery ho nemaji vyplneny … bohuzel se mi nedari pouzivat ten parametr ktery se vytahuje z casti USING ( … ) jako parametr do te fce …

      Tak co? date to? je to real priklad.. fakt si s tim nevim rady .. fce mi vraci 99999 coz je cast z EXCEPTIONS WHEN OTHERS THEN RETURN 99999;

      CREATE OR REPLACE PROCEDURE proc_set_irr ( p_table_name IN VARCHAR2, p_cashflow_column IN VARCHAR2, p_dimension IN VARCHAR2, p_irr_column IN VARCHAR2 )

      IS

      BEGIN

      execute immediate replace(repla­ce(replace(re­place(

      q'[

      merge into #P_TABLE_NAME#

      using

      (

      select distinct #P_DIMENSION#

      from #P_TABLE_NAME#

      where #P_IRR_COLUMN# is null

      ) null_irr

      on (null_irr.#P_DI­MENSION# = #P_TABLE_NAME#­.#P_DIMENSION#)

      when matched then update set

      #P_IRR_COLUMN# = f_calc_irr(

      ‚#P_TABLE_NAME#‘,

      ‚#P_CASHFLOW_CO­LUMN#‘,

      '#P_DIMENSION# = '||null_irr.#P_DI­MENSION#)*100

      ]'

      , ‚#P_TABLE_NAME#‘, p_table_name)

      , ‚#P_DIMENSION#‘, p_dimension)

      , ‚#P_IRR_COLUMN#‘, p_irr_column)

      , ‚#P_CASHFLOW_CO­LUMN#‘, p_cashflow_column

      );

      commit;

      EXCEPTION

      WHEN OTHERS THEN

      dbms_output.put_li­ne(DBMS_UTILI­TY.FORMAT_ERROR_STAC­K||DBMS_UTILI­TY.FORMAT_ERROR_BAC­KTRACE);

      END proc_set_irr;

      /

      • Rorejs74  

        Uplne mi ten zapis neni jasnej, ale pripada mi ze na to jdes moc slozite.

        Proc nepouzijes tu funkci uz v samotnym selectu a snazis se misto toho updatovat tu worktable ?

        Ve stylu :

        select f_calc_irr( …

        from #P_TABLE_NAME#

        where #P_IRR_COLUMN# is null

        • Rorejs74  

          Pripadne pokud je ta #P_TABLE_NAME# realna tabulka tak :

          update #P_TABLE_NAME#

          set #P_IRR_COLUMN# = f_calc_irr( …

          from #P_TABLE_NAME#

          where #P_IRR_COLUMN# is null

          • c0d3r  

            protoze tu hodnotu musim spocitat pro kazdou smlouvu samostatne a pri stotisicich smluv je tohle reseni pres UDPATE extremne pomale …

            musim si totiz nejprve vytahnout vsechny smlouvy z tabulky jako unikatni hodnoty (protoze v tabulka obsahuje jejich cashflow ⇒ tzn kazda smlouva ma >1record ) a pak je musim one-by-one update.ovat a do funkce musim predat parametr tu konkretni smlouvu …

            tohle reseni jsem samozrejme zkousel, nicmene to je extremne narocne na CPU a trva to mraky hodin … hledam proto optimalizovanou verzi kvuli vykonu ..

            • Rorejs74  

              Hmm, tak pak bych si asi nejdriv hodil tu mnozinu smluv do #temp tabulky a updatoval to v nejakych mensich davkach, nebo to udelal pres cursor, ale to by rychlostne asi moc nepomohlo.

              Teoreticky by stacilo tam jenom stacilo nastavit nejakej vhodnej rowcount a volat to opakovane … pokud teda je zajisteno ze ta funkce nemuze vratit hodnotu null :)

              • c0d3r  

                jj to je reseni ktery ted hodlam implementovat… data se tam loadujou po mesici tak to budu volat po dnech (coz je celkem psycho ale co uz) .. prusvih je, ze mame nastavenej limit na „CPU usage“ .. tzn skript bezi max hodinu .. (na-update-ovat celej mesic mi trva cca 5× volani skriptu → tzn cca 5 h) takze to budu muset celou tu proceduru volat nekolikrat .. coz nemam moc radost :D a je to prasarna ale kdyz to zacyklim v procedure tka mi to po hodine spadne .. doufam ze kdyz zavolam pet procedur tak to bude releasovat CPU usage a nebude to padat (v ramci package)

              • Rorejs74  

                Nejak takhle :

                set rowcount 1000

                while ( exists( select 1 from #P_TABLE_NAME# where #P_IRR_COLUMN# is null ) )

                begin

                update #P_TABLE_NAME#

                set #P_IRR_COLUMN# = f_calc_irr( …

                from #P_TABLE_NAME#

                where #P_IRR_COLUMN# is null

                -- mozna nejakej waitfor pokud nechces extra zatezovat server jen pro sebe

                end

                • c0d3r  

                  dik… presne neco takovyho napisu .. ten wait asi neni potreba. load probiha v noci, takze by to nemelo tolik zatizit

                  • Rorejs74  

                    Jasne, zalezi jestli je prioritou doba behu nebo minimalne zatez CPU. Ja ty waitfory celkem pouzivam i kvuli tomu aby se stihal odlejvat transakcni log pokud jsou to vetsi operace a taky abych moc nezahlcoval replikacni server a pak z toho nebyli operatori vedle :))

    • lukas aka mitro  

      …sama databazova cicovina:)

      • look_as1  

        To jo, jsem myslel, ze relacni databaze uz nikdo nedela.

        Nebo je aspon nepouziva jako relacni :-)

      • Bucci  

        Relační databáze jsou sice za zenitem, ale budou tu s námi ještě dost dlouho. O to se neboj.

        Ale jestli vás to už nebaví, můžeme dát céčko. Nebo byste raději zas nějaké šifry?

      • hekynen  

        DROP DATABASE ALL

    • Rorejs74  

      Mam tu pro zajimavost jeden pripad z praxe ( optimalizace SQL na Sybase ASE ) :

      Mam tabulku :

      create table wib_login_log (

      USR_login T_USER not null,

      DAT_kdy T_DAT not null,

      S50_ip_address T_S50 not null,

      PEN_akce T_PEN not null,

      S255_browser T_S255 null,

      constraint PK_WIB_LOGIN_LOG primary key (USR_login, DAT_kdy)

      )

      go

      aktualne to ma cca 50mil zaznamu.

      Potrebuju co nejlepe zjistit posledni zaznam pro daneho uzivatele :

      Jednoducha varianta :

      select max( DAT_kdy )

      from wib_login_log

      where ( USR_login = „fantomas“ ) and

      ( PEN_akce = 790001 )

      Ale ten udela tohle :

      STEP 1

      The type of query is SELECT.

      Evaluate Ungrouped MAXIMUM AGGREGATE.

      FROM TABLE

      wib_login_log

      Nested iteration.

      Using Clustered Index.

      Index : PK_WIB_LOGIN_LOG

      Forward Scan.

      Positioning by key.

      Keys are:

      USR_login ASC

      Using I/O Size 16 Kbytes for index leaf pages.

      With LRU Buffer Replacement Strategy for index leaf pages.

      Using I/O Size 16 Kbytes for data pages.

      With LRU Buffer Replacement Strategy for data pages.

      STEP 2

      The type of query is SELECT.

      Table: wib_login_log scan count 1, logical reads: (regular=387 apf=0 total=387), physical reads: (regular=284 apf=5 total=289), apf IOs used=4

      Total writes for this command: 0

      (1 row affected)

      To sice neni uplne spatne, ale uplne idealni to taky neni.

      Takze ukol zni jak to udelat rychleji a lepe z hlediska optimalizace … reseni je pomerne jednoduchy, ale nemusi napadnout hned ;-)

      • Bucci  

        Pokud to má být poslední ve smyslu pořadí vložení do DB, co zkusit největší rowid?

        • Rorejs74  

          Je to posledni zaznam pro daneho uzivatele, takze to Ti nepomuze. Navic potrebujes nejvyssi datum, takze by to teoreticky ani nemusela byt pravda ( i kdyz zrovna tady inserty „do minulosti“ neprobihaji ).

          • RomanH  

            Ciste teoreticky, nebylo by to mene narocne pres otoceny index (den s casem a nasledne uzivatel) ?

            • Rorejs74  

              Tady urcite ne, jsou tam radove desetitisice zaznamu za jeden den, zatimco pro jednoho uzivatele jsou jich tam maximalne stovky.

              Navic jakakoliv takovahle manipulace ( treba blby pridani indexu ) s takhle velikou tabulkou uz je dost problem.

      • Bucci  

        Tak se asi dávám poddat …

      • MichaelSimek  

        a nestacilo by to i zgroupovat? pak udela nejdriv where pak group a pak teprve agr fce ne?

        • Bucci  

          Nechápu. Nejdriv where pak group a pak teprve agr fce … A pak jako znovu group? Nebo jak jsi to myslel?

          Jinak k Rorejsovi74 mě napadá ještě jeden postup: Použít funkci LEAD(DAT_kdy, 1) OVER (PARTITION BY USR_login ORDER BY DAT_kdy) AS DAT_next, a z logiky věci pak vyplývá, že v tom řádku, kde bude DAT_next NULLové, bude DAT_kdy největší pro daný USR_login. Tento algoritmus používáme u nás v konstrukci „inteligentního“ duplicate checkeru, který má vyhazovat všechny řádky s duplicitním ID kromě jediného (např. toho nejnovějšího).

          Ale pochybuji, že by to bylo rychlejší než obyčená aggr fce s jedním group by.

          • Rorejs74  

            Tak v tomhle pripade mam celkem oblibenou flignu ( na Sybase to funguje 100% ), ktera spociva v tom donutit ho jet ten index sestupne.

            Takze zapis pak vypada takhle :

            set rowcount 1

            select DAT_kdy

            from wib_login_log

            where ( USR_login = „fantomas“ ) and

            ( PEN_akce = 790001 )

            order by USR_login desc, DAT_kdy desc

            Optimalizace pak ukazuje :

            STEP 1

            The type of query is SELECT.

            FROM TABLE

            wib_login_log

            Nested iteration.

            Using Clustered Index.

            Index : PK_WIB_LOGIN_LOG

            Backward scan.

            Positioning by key.

            Keys are:

            USR_login ASC

            Using I/O Size 16 Kbytes for index leaf pages.

            With LRU Buffer Replacement Strategy for index leaf pages.

            Using I/O Size 16 Kbytes for data pages.

            With LRU Buffer Replacement Strategy for data pages.

            Table: wib_login_log scan count 1, logical reads: (regular=3 apf=0 total=3), physical reads: (regular=2 apf=0 total=2), apf IOs used=0

            • Bucci  

              A jak z toho pak vytáhneš ten MAX?

              • RomanH  

                ma tam na pocatku set rowcount 1 a pak order. Na MSSQL by to teoreticky slo i pres SELECT TOP 1 … ORDER BY

                Pouzivam to obcas v subquery. Chce to porovnavat dle skutecneho obsahu dat.

                • Rorejs74  

                  Presne tak, set rowcount 1 je v tomhle pripade ekvivalent k TOP 1

                  Takze vlastne po nem chci sestupne setrideny seznam o 1 zaznamu, cimz si to optimalizator spravne prebere tak, ze muze jit po indexu od vrchu – backward scan ( samozrejme pokud je ten index vytvorenej jako ASC ). Taky proto je tam v order by ten USR_login i kdyz to fakticky nema smysl, kdyz je to ve where stejne omezeny jen na jednoho.

                  Dalsi vyhodou tohohle je, ze se to da pustit na isolation level 0 ( uncommitted read ), coz treba v pripade pouziti GROUP BY neudelas.

    • Bucci  

      Zkusím oživit tohle staré, ale pěkné vlákno.

      Hádanka: Kolik je 1++ ?

      • Tacmud  

        Koukám, že je to návrat k naprostým základům!

        Výsledek = 2

        … a další hádanka: jak se liší výsledek po provedení příkazů:

        j = i =1;

        j = i++ ;

        a nebo

        j = i = 1;

        j = ++i;

        ???

        • wilda81  

          1

          2

          • hekynen  

            2

            1

            • Tacmud  

              Napsal bych to takto:

              v prvním případě i=2 ; j=1;

              v druhém i=2 ; j=2;

              • hekynen  

                hmm, je zajímavé, že po 17 hodinách u počítače už na takové píčovinky nemám nějak hlavu ani náladu.. :-)

                • Tacmud  

                  To chápu. Já mám dovolenou a už 2 dny jsem nebyl u kompu! ;-)

                  • hekynen  

                    A to já si zase dnes moc hezky zaprogramoval! :-D

                    • Tacmud  

                      apropo včem bastlíš?

                      • hekynen  

                        Dnes na menu bylo:

                        – Visual Basic – nějaké bastlení v Účetnictví (DPH, EET)

                        – Transact-SQL (pro MSSQL 2000, 2005, 2008, 2012, 2014) – dělal jsem nějaké univerzální servisní a informační skripty

                        – VB script – spouštění těch T-SQL skriptů (podle verze SQLka) s výstupy do csv

                        – jo a ještě byla jedna migrace SQL databáze

                        Ještě dělám pár projektů v C#, na ty ale dnes nedošlo. :-)

                        Vlastně teda včera. Kua, jdu chrápat…

                • wilda81  

                  Přesně proto tyhle zkrácené zápisy, linq apod. nemám moc rád. Raději delší a přehledný zápis, ať pak za půl roku při bigfixingu (a po X pivech) nepřemýšlím: „co ten kus kódu vlastně dělá?!“

                  • Tacmud  

                    Takovéhle základy snad musí dát každý průměrný programátor automaticky napoprvé i po 8. pivě nebo po 5. velkém rumu!

                    Nemám rád dlouhý a ukecaný kódy! Mám radši 20 znaků kódu a k tomu 5 řádků komentáře, než dlouhej a ukecanej kód bez komentářů.

                    • wilda81  

                      Zajímavé, že tyhle „silácké řeči“ většinou rychle skončí hned jak někomu zadám ať upraví/opraví kód po podobně smýšlejícím kolegovi jako jsi ty. ;-) Stačí blok s řetězením několika linq dotazů, plný lambda výrazů, predikátů, delegátů, ideálně ještě s asynchroním voláním a při první potřebě debugování se začne karta obracet. Nejvíce je to vidět když se objeví nějaký víkendový servis, kluci chtějí problém rychle opravit a mít zase klid :)

                      Neříkám, že je něco špatně nebo dobře. Je jen důležité, aby si celý tým našel stejnou cestu/standard, všichni pak zápisu rozuměli a dodržovali jej. Tím se pak právě eliminují problémy při následných úpravách.

                      Ideální je tzv. „self-explanatory code“, který má smysluplně pojmenované vlastnosti, metody atd. Pak není potřeba téměř komentovat…

                      • lukas aka mitro  

                        Ja to vidim tak, ze casto je je to efektivita/vykon vs rychlost. U mne je to ale trochu extrem, bo vsechno delam (snazim se delat) s maticema. Jedna operace muze byt na vice nebo na jeden radek. Ta na jeden radek svisti jak z praku, ta delsi ne. Ale da se to udelat i naopak:) Hodne lidi programuje tak, aby kod nezabiral moc mista…a to je pak prasarna. Navic kdyz ti kompilator umozni viceurovnove inline…

                        Treba nedovno, blbnu s fortranem (proc? bo C a derivaty nemaji dobre zmaknutou komplexni algebru), napisu us kodu, otestuju a pomale jak prase…nejake nasobeni mnoha matic vektorem. Dumam, dumam. Pripisu at si vektor misto do pameti ulozi do cache a uz to svisti:)

                      • hekynen  

                        Já jsem v tomto prostě stará škola. Kód má být přehledný, má být zjevné, co dělá, vhodně okomentovaný, proměnné, funkce apod. pojmenované podle toho, co nosí, dělají. U proměnných pak vždy prefix typu. Už jsem párkrát předělával (přebíral) program, kde proměnné byly pojmenovány (teda skoro) X1 – Xnnn.

                        Zrovna teď jsem hledal „záhadnou“ chybku ve svém kódu. Čtyři hodiny… No, našel. A to díky správně pojmenované proměnné (cpal jsem tam jinou).

                        A taky jsem se naučil (a to hlavně), komentovat změny. Kdy, kým, co, proč, kdo, kdy a jak zadal – 20161228Heky změna výpočtu, má se odečíst i xxx (email Debil, 28/12/2016) ;-)

                        • lukas aka mitro  

                          %% zmeneno XX.XX.XXXX, nefungovalo a a stale nefunguje…

                          • hekynen  

                            Komenty vyjadřující můj skutečný stav a mysli jsem se odnaučil používat před cca 20 lety. Ano, uznávám, že komentáře typu „Pičovina! Pičovina!! PIČOVINA!!!“, „Na to mrdám“, „Nebudu to dělat!“, „Nechápu teda sice vůbec proč, ale ta piča to takhle chce!“ jsou sice přesné, nicméně po nějakém čase jsou lehce zavádějící.

                            Ono hlavně, když pak ten zdroják předáš zadavatelovi…

                            • Bucci  

                              Analytička: „Ježíšikriste! Co to je na tom sharu!?“

                              Programátor: „No coby, udělal jsem si tam tři testovací soubory … “

                              Analytička: „Dobře, ale to jsi je opravdu musel nazvat psi_hovno.tmp, krysi_kunda.tmp a byci_curak.tmp?“

                    • blaf  

                      20 znaků kódu s nutnými pěti řádky komentáře je opravdu hodně spatnej kód!

                      • Tacmud  

                        Trochu jsem přeháněl. Praxe bývá jiná.

                        Na komentáře nebývá moc času.

                      • lukas aka mitro  

                        neco jako:

                        limit_imag=0.05;

                        a = (abs(imag(V0))>li­mit_imag);

                        up = a .* (imag(V0)<0) + ~a .* (real(V0)-imag(V0)<0);

                        [upsort,ii]=sor­t(up,1,‚descen­d‘);

                        aneb aby to jelo rychle, doprasime to pres logicke a aritmeticke operatory najednou:)))

                        • blaf  

                          Když je to opodstatněné tak je to o něčem jiném. Ve většině případů je ale optimalizace zbytečná a jen znepřehledni kód. Myslím, že většina tu nedělá raketovou vědu.

                          • lukas aka mitro  

                            Jj…obcas se to hodi. Nedavno jsem delal nejakou optimalizaci doku a pri profilovani jsem narazil na mou fci, ktera trvala 0.1s…jenom nejake debilni preusporadavani matic. Pruser byl, ze se ta fce mela desitky tisic volani, takze jsme dva dny dumal a testoval jak ji urychlit:)

      • hekynen  

        A kolik ++1? ;-)

        • Tacmud  

          nakonec taky 2 ;-)

          • blaf  

            mi to pise „Uncaught ReferenceError: Invalid left-hand side expression in prefix operation“ :)

            • Tacmud  

              asi existuje výce programovacích jazyků.

              • blaf  

                Tohle je z js z chromu. js samozřejmě ++ umí, ale jde o to 1++. var a = 1; ++a; fungovat bude. 1 je literal a ten nezměníš.

      • Bucci  

        Tak abyste věděli, 1++ byl chyták, protože konstantu nelze inkrementovat. :-PPP Správná odpověď je tedy compile error: lvalue required as increment operand.

    • plzakj  

      Pekne tema :-) Tak ja taky jeden pridam.

      i = 1;

      if ( i > 0 );

      i++;

      Kolik je i?

      • vt  

        nejspis 2 :-) … if bez body je pekna prasarna, to by snad ani nemelo jit zkompilovat :-)

        • hovado_cz  

          na to sere bílej tesák… bejvalej zaměstnavatel říkal „hlavně ať to funguje“ :-)

        • plzakj  

          Dohaje :-D Melo tam bejt if( i < 0); :-D Takhle to nema to kouzlo a je to faux paux. Ano 2. V opacnem pripade 1. Protoze ; je (aspon v C/C++) validni prikaz po ifu. Pak zalezi na kompilatoru, jestli vypoti aspon warning. Nebyva to zamer, vetsinou chyba ktera se snadno prehlidne :-)

          • vt  

            prijde mi, ze na ty podmince nezalezi, takze to skonci vzdy 2 ;-)

    • grafik  

      Databaze jsou nuda.

      C++

      Zapiste: Pointer na pole pointeru. Libovolne velike pole. Z ukazatelu ziskejte hodnoty, sestavte buffer a odeslete pomoci socketu na jine pc, kde obsah bufferu vypisete. Buffer zajistete crc, identifikatorem a casovou znackou.

      • wilda81  

        To zní jako zadání úkolu, který se ti nechce dělat :))

      • plzakj  

        Jezis. To je nejakej domaci ukol ze skoly ne? :-)

      • hekynen  

        Já se na to, já to nebudu dělat, já to mrdám. To musíš celé sání, turbo, všecko odšrubovat.

        Já to nejdu dělat! Né!

        Kristova hodina vole, toto je kurva stroj, ty pičo.

        • hekynen  

          No ovšem, zapomněl jsem na „To je past vedle pasti, pičo“.

          Omlouvám se.

          Nikdo není dokonalý. Dokonce ani já ne.

    • Bucci  

      A něco o třídu níže:

      C

      #include <stdio.h>

      #include <stdlib.h>

      int main(int argc, char** argv) {

      int i = 5;

      int j = 6;

      int *p = &i;

      int *q = &j;

      i += 2;

      j = ++i * (*q / 2);

      p = q;

      *q = *p – i;

      i++;

      q = &i;

      *p = *p + *q – j + i;

      printf(„%d %d\n“, i, j);

      return(0);

      }

      Co bude výstupem programu?

    • plzakj  

      A ted jeden ze 22.12. v praci (i je tam navic):

      bool *b;

      int i = 0;

      if (b)

      {

      *b = false;

      i++;

      }

      i++;

      Kolik je i a proc? (existuji 2 spravne odpovedi :-)

      • lukas aka mitro  

        2, *b bude nenulove, tedy to skoci do ifu, tam hodnota na pole oukazatele nastavi na fase, cimz to zablokue dalsi cyklus, i v cyklu je 1 a po cyklu inkrementije na 2.

        • plzakj  

          Jo. Ten neNULLovanej pointer je peklo. 22 jsem do toho debuggeru cumel asi pul hodiny, nez jsem svimnul ty priciny. On ten bool* byl puvodne member struktury, ale nechtel jsem ti tu komplikovat.

          Jinak ten muj example je trochu blbe :-) Melo tam bejt „b = new bool(false)“.

          BTW: dynamicky alokovanej boolean je kapitola dama pro sebe. Autora bych klepnul pres ruce. Jeste tam seknul tuhle botu…

        • Bucci  

          Ehm, kde tam vidíš nějaký cyklus?

      • Bucci  

        Neinicializovaný pointer *b může ukazovat na libovolnou adresu, platnou i neplatnou. V podmínce na řádku 3 se navíc vyhodnocuje hodnota pointeru, nikoli referencovaného místa v paměti. Takže pokud by čistě náhodou pointer *b obsahoval adresu 0000 (což by se automaticky zcastovalo na false), blok if by se neprovedl a provedla by se jen inkrementace na konci, takže výsledná hodnota i by byla 1.

        Ovšem mnohem pravděpodobnější je, že pointer *b bude obsahovat nějakou jinou adresu, která však není naalokovaná, a proto program spadne v momentě, kdy se do ní pokusí zapsat. Tedy Segmentation fault na řádku 5.

        • plzakj  

          Jo, je to tak. Ta pravdepodobnejsi varianta skutecne nastavala. Crash jsem opravil o par komentu vyse :-)

          • plzakj  

            Jaj. Ted jsem si precetl pravidla :-) Jsem je asi porusil. Co uz, sorac :-)

          • Bucci  

            Jo, ve firmách občas vyplavou na světlo věci, že by člověk žasnul. Já jednou našel zhruba toto:

            (Java)

            if (a == b) {

            // nějaký kód, neměnící a ani b

            if (a != b) {

            // cca 100 řádků kódu, řešících jeden z účetních případů

            }

            }

            A běželo to tam asi tak 4 měsíce. Škodu raději nikdo nezkoušel vypočítat.

            • plzakj  

              :-)

              Osvedcily se nam nastroje na statickou analyzu. Na Javu Sonar. Na C/C++ Coverity (javu umi taky).

            • hekynen  

              V poho, účto toho snese hodně. Jen u mezd občas lidi řvou… Zejména pokud nedostanou výplatu. ;-)

    • Bucci  

      Tak já zkusím něco zadat:

      Napište v C program s nekonečnou smyčkou, která každých 5 minut zapíše do logu aktuální timestamp. Ale pozor! Program musí běžet jako unixový démon.

    • Bucci  

      Ach jo. :-(

      Tak vy se tady chvástáte, že databáze jsou pro vás nuda, ale když na vás člověk vytáhne trochu vyšší dívčí, tak je najednou ticho po pěšině …

      • hovado_cz  

        ale dobrej nápad, až budu potřebovat do práce napsat nějakej plugin tak to hodim sem jako „zábavu“ :D

      • plzakj  

        Musis neco, co se da resit z hlavy ;-) Kodovani mam dost z prace.

        • Bucci  

          Vždyť ten démon je na 30 řádků …

          #include <stdio.h>

          #include <stdlib.h>

          #include <unistd.h>

          // aby se stal demonem, musi platit PID == PGID == SID && PPID == 1

          int main(int argc, char **argv) {

          switch(fork()) {

          case –1:

          printf(„Nepodarilo se odstepit proces.\n“);

          exit(1);

          case 0:

          // potomek

          break;

          default:

          // rodic

          return(0);

          }

          if(setsid() < 0) {

          printf(„Nepodarilo se vytvorit session.\n“);

          exit(1);

          }

          chdir(„/“);

          umask(0);

          for( ; ; ) {

          // funkcni logika

          }

          }

        • hovado_cz  

          asi tak, navíc proč řešit programátorský rébusy na bike-fóru :-) jako kdyby neexistovalo žádný programátorský fórum :-D

    • Bucci  

      Tak z jiného soudku (získávání informací):

      Jakýmkoli způsobem zjistěte, jestli Valeria Kurnuškina žije, nebo jestli zahynula v letadle s ostatními Alexandrovci. :-(

      (Když se to stalo, googlil jsem celý večer, ale nenašel nic … )

Nová reakce na zakládající

Pro napsání příspěvku se prosím přihlaste nebo zaregistrujte.

Podobné diskuse