sql >> Database teknologi >  >> Database Tools >> SSMS

Datointerval for sæt af samme data

Ikke-relationel løsning

Jeg tror ikke, at nogen af ​​de andre svar er rigtige.

  • GROUP BY virker ikke

  • Bruger ROW_NUMBER() tvinger dataene ind i en Record Filing System-struktur, som er fysisk, og behandler dem derefter som fysiske poster. Til enorme præstationsomkostninger. For at kunne skrive en sådan kode tvinger det dig selvfølgelig til at tænke i form af RFS i stedet for at tænke i relationelle termer.

  • Brug af CTE'er er det samme. Iteration gennem data, især data, der ikke ændrer sig. Til en lidt anderledes massiv pris.

  • Markører er bestemt den forkerte ting af forskellige årsager. (a) Markører kræver kode, og du har anmodet om en visning (b) Markører forlader sæt-behandlingsmotoren og vender tilbage til række-for-række-behandling. Igen, ikke påkrævet. Hvis en udvikler på et af mine teams bruger markører eller midlertidige tabeller på en relationsdatabase (dvs. ikke et registreringssystem), skyder jeg dem.

Relationel løsning

  1. Dine data er Relationel, logisk, de to givne data kolonner er alt, hvad der er nødvendigt.

  2. Selvfølgelig skal vi danne en visning (afledt relation) for at opnå den ønskede rapport, men den består af rene SELECT'er, som er helt anderledes end behandling (konvertering til en fil , som er fysisk, og derefter behandle filen; eller vikarborde; eller arbejdsborde; eller CTE'er; eller ROW_Number(); osv.).

  3. I modsætning til beklagelserne fra "teoretikere", som har en dagsorden, håndterer SQL Relationelle data udmærket. Og dine data er relationelle.

Oprethold derfor en Relationel tankegang, en Relationel opfattelse af dataene og en set-bearbejdningsmentalitet. Ethvert rapportkrav over en relationsdatabase kan opfyldes ved hjælp af et enkelt SELECT. Der er ingen grund til at gå tilbage til ISAM-filhåndteringsmetoder før 1970.

Jeg vil antage, at den primære nøgle (det sæt af kolonner, der giver en relationel række unikke) er Date, og baseret på de angivne eksempeldata er datatypen DATE.

Prøv dette:

    CREATE VIEW MyTable_Base_V          -- Foundation View
    AS
        SELECT  Date,
                Date_Next,
                Price
            FROM (
            -- Derived Table: project rows with what we need
            SELECT  Date,
                    [Date_Next] = DATEADD( DD, 1, O.Date ),
                    Price,
                    [Price_Next] = (

                SELECT Price            -- NULL if not exists
                    FROM MyTable
                    WHERE Date = DATEADD( DD, 1, O.Date )
                    )

                FROM MyTable MT

                ) AS X
            WHERE Price != Price_Next   -- exclude unchanging rows
    GO

    CREATE VIEW MyTable_V               -- Requested View
    AS
        SELECT  [Date_From] = (
            --  Date of the previous row
            SELECT MAX( Date_Next )     -- previous row
                FROM MyTable_V
                WHERE Date_Next < MT.Date
                ),

                [Date_To] = Date,       -- this row
                Price
            FROM MyTable_Base_V MT
    GO

    SELECT  *
        FROM MyTable_V
    GO

Metode, generisk

Selvfølgelig er dette en metode, derfor er den generisk, den kan bruges til at bestemme From_ og To_ af ethvert datainterval (her en Date interval), baseret på enhver dataændring (her en ændring i Price). ).

Her er dine Dates er fortløbende, så bestemmelsen af ​​Date_Next er enkel:forøg Date inden for 1 dag. Hvis PK er stigende, men ikke fortløbende (f.eks. DateTime eller TimeStamp eller en anden nøgle), ændre den afledte tabel X til:

    -- Derived Table: project rows with what we need
    SELECT  DateTime,
            [DateTime_Next] = (
            -- first row > this row
        SELECT  TOP 1
                DateTime                -- NULL if not exists
            FROM MyTable
            WHERE DateTime > MT.DateTime
            ),

            Price,
            [Price_Next] = (
            -- first row > this row
        SELECT  TOP 1
                Price                   -- NULL if not exists
            FROM MyTable
            WHERE DateTime > MT.DateTime
            )

        FROM MyTable MT

God fornøjelse.

Du er velkommen til at kommentere, stille spørgsmål osv.



  1. Hvad er problemet med 10-cifret mobil uden data i mysql?

  2. MYSQL:Sådan gør du NULL eller tomme data som standard til 0 under indsættelse

  3. phpmyadmin fejl under installationen Tom værdi for 'port' angivet.

  4. Hvad er den nemme måde at importere stor database til mysql ved hjælp af phpmyadmin?