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

Datumbereik voor set van dezelfde gegevens

Niet-relationele oplossing

Ik denk niet dat een van de andere antwoorden juist is.

  • GROUP BY werkt niet

  • ROW_NUMBER() gebruiken dwingt de gegevens in een Record Filing System-structuur, die fysiek is, en verwerkt deze vervolgens als fysieke records. Tegen enorme prestatiekosten. Om zo'n code te schrijven, moet je natuurlijk nadenken in termen van RFS in plaats van in relationele termen te denken.

  • Het gebruik van CTE's is hetzelfde. Itereren door de gegevens, vooral gegevens die niet veranderen. Tegen een iets andere enorme prijs.

  • Cursors zijn absoluut het verkeerde ding om een ​​andere reeks redenen. (a) Cursors hebben code nodig en u hebt een View aangevraagd. (b) Cursors verlaten de set-processing-engine en keren terug naar rij-voor-rij-verwerking. Nogmaals, niet vereist. Als een ontwikkelaar in een van mijn teams cursors of tijdelijke tabellen gebruikt in een relationele database (dus niet in een archiefsysteem), schiet ik ze.

Relationele oplossing

  1. Uw gegevens is relationeel, logisch, de twee gegeven gegevens kolommen zijn alles wat nodig is.

  2. Natuurlijk moeten we een View (afgeleide relatie) vormen om het gewenste rapport te verkrijgen, maar dat bestaat uit pure SELECT's, wat heel wat anders is dan verwerken (het converteren naar een bestand , wat fysiek is, en vervolgens het bestand . verwerken; of tijdelijke tabellen; of werktafels; of CTE's; of ROW_Number(); enz.).

  3. In tegenstelling tot de klaagzangen van "theoretici", die een agenda hebben, gaat SQL prima om met relationele gegevens. En uw gegevens zijn relationeel.

Zorg daarom voor een relationele mentaliteit, een relationele kijk op de gegevens en een mentaliteit voor het verwerken van sets. Aan elke rapportagevereiste over een relationele database kan worden voldaan met een enkele SELECT. Het is niet nodig om terug te gaan naar ISAM-bestandsverwerkingsmethoden van vóór 1970.

Ik ga ervan uit dat de primaire sleutel (de reeks kolommen die een relationele rij-uniciteit geven) Date, is en op basis van de gegeven voorbeeldgegevens is het gegevenstype DATE.

Probeer dit:

    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

Methode, algemeen

Dit is natuurlijk een methode, daarom is het generiek, het kan worden gebruikt om de From_ te bepalen en To_ van elk gegevensbereik (hier een Date, bereik), op basis van een gegevenswijziging (hier een wijziging in Price ).

Hier, uw Dates zijn opeenvolgend, dus de bepaling van Date_Next is eenvoudig:verhoog de Date, met 1 dag. Als de PK toeneemt maar niet opeenvolgend (bijv. DateTime of TimeStamp of een andere sleutel), verander de afgeleide tabel X naar:

    -- 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

Geniet ervan.

Voel je vrij om commentaar te geven, vragen te stellen, enz.



  1. Hoe krijg ik toegang tot mysql vanaf mac-terminal met xampp?

  2. phpMyAdmin De map die u hebt ingesteld voor uploadwerk kan niet worden bereikt

  3. Toegang geweigerd fout tijdens het verbinden met MySQL in App in Azure App Service

  4. Hoe de datatypes van de resultaten van een SQL bepalen?