sql >> Databáze >  >> RDS >> Sqlserver

Zobrazit pro identifikaci seskupených hodnot nebo objektů

Druhá odpověď je již pěkně dlouhá, takže ji nechávám tak, jak je. Tato odpověď je mnohem lepší, jednodušší a také správná, zatímco ta druhá má některé okrajové případy, které vedou k nesprávné odpovědi – toto cvičení nechám na čtenáři.

Poznámka:Pro přehlednost jsou přidány konce řádků. Celý blok je jeden dotaz

;with Walker(StartX,StartY,X,Y,Visited) as (
    select X,Y,X,Y,CAST('('+right(X,3)+','+right(Y,3)+')' as Varchar(Max))
    from puzzle
    union all
    select W.StartX,W.StartY,P.X,P.Y,W.Visited+'('+right(P.X,3)+','+right(P.Y,3)+')'
    from Walker W
    join Puzzle P on
      (W.X=P.X   and W.Y=P.Y+1 OR   -- these four lines "collect" a cell next to
       W.X=P.X   and W.Y=P.Y-1 OR   -- the current one in any direction
       W.X=P.X+1 and W.Y=P.Y   OR
       W.X=P.X-1 and W.Y=P.Y)
      AND W.Visited NOT LIKE '%('+right(P.X,3)+','+right(P.Y,3)+')%'
)
select X, Y, Visited
from
(
    select W.X, W.Y, W.Visited, rn=row_number() over (
                                   partition by W.X,W.Y
                                   order by len(W.Visited) desc)
    from Walker W
    left join Walker Other
        on Other.StartX=W.StartX and Other.StartY=W.StartY
            and (Other.Y<W.Y or (Other.Y=W.Y and Other.X<W.X))
    where Other.X is null
) Z
where rn=1

Prvním krokem je nastavení "walker" rekurzivního tabulkového výrazu, který bude začínat v každé buňce a bude cestovat tak daleko, jak jen to půjde, aniž by musel opakovat jakýkoli krok. Ujištění, že buňky nejsou znovu navštěvovány, se provádí pomocí navštíveného sloupce, který ukládá každou buňku, která byla navštívena z každého počátečního bodu. Konkrétně tato podmínka AND W.Visited NOT LIKE '%('+right(P.X,3)+','+right(P.Y,3)+')%' odmítne buňky, které již navštívil.

Abyste pochopili, jak zbytek funguje, musíte se podívat na výsledek generovaný CTE „Walker“ spuštěním „Select * from Walker order by StartX, StartY“ po CTE. "Kus" s 5 buňkami se objeví alespoň v 5 skupinách, každá s jiným (StartX,StartY) , ale každá skupina má všech 5 (X,Y) kusy s různými „navštívenými“ cestami.

Poddotaz (Z) používá LEFT JOIN + IS NULL k vyřazení skupin do jednoho řádku v každé skupině, která obsahuje "první souřadnici XY", definovanou podmínkou

     Other.StartX=W.StartX and Other.StartY=W.StartY
        and (Other.Y<W.Y or (Other.Y=W.Y and Other.X<W.X))

Záměrem je, aby každá buňka, kterou lze navštívit počínaje (StartX, StartY), porovnala mezi sebou buňku ve stejné skupině a našla buňku, kde ŽÁDNÁ OSTATNÍ buňka není na vyšším řádku, nebo pokud jsou na stejný řádek, je vlevo od této buňky. To nám však stále nechává příliš mnoho výsledků. Zvažte pouze 2-článkový kus na (3,4) a (4,4):

StartX  StartY  X   Y   Visited
3       4       3   4   (3,4)          ******
3       4       4   4   (3,4)(4,4)
4       4       4   4   (4,4)
4       4       3   4   (4,4)(3,4)     ******

Zbývají 2 řádky s "první souřadnicí XY" z (3,4), označené ****** . Potřebujeme pouze jeden řádek, takže použijeme Row_Number, a protože číslováme, mohli bychom jít na nejdelší Visited cesta, která by nám dala tolik buňky uvnitř kusu, jak můžeme získat.

Poslední vnější dotaz jednoduše vezme první řádky (RN=1) z každé podobné (X,Y) skupiny.

Chcete-li zobrazit VŠECHNY buňky každého kusu, změňte řádek
select X, Y, Visited

uprostřed do

select X, Y, (
    select distinct '('+right(StartX,3)+','+right(StartY,3)+')'
    from Walker
    where X=Z.X and Y=Z.Y
    for xml path('')
    ) PieceCells

Které poskytují tento výstup

X           Y           PieceCells
1           1           (1,1)(2,1)(2,2)(3,2)
3           4           (3,4)(4,4)
5           6           (5,6)
7           5           (7,5)(8,5)(9,5)
8           1           (10,1)(8,1)(8,2)(9,1)(9,2)(9,3)


  1. SQL klient pro Mac OS X, který spolupracuje s MS SQL Server

  2. Seznam uživatelů přistupujících k databázi

  3. Připojte datové rámce pandas na základě hodnot sloupců

  4. pdo vložit obrázek přímo do databáze - vždy vkládat BLOB - 0B