Query/View: The 2 newest periods for each indicator

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Ryan Dahl

    Query/View: The 2 newest periods for each indicator

    Hi,

    I'm working on a simple performance-program, where I need to extract
    information from the 2 newest periods for every performance-indicator
    - And from there calculate a trend between these results.

    The problem is, that I can't find a simple way to extract the 2 latest
    results.

    The Table (Table1) looks like this:
    kpiID periodID Actual
    Acceleration 2 3
    Acceleration 5 4
    Speed 1 100
    Speed 4 200
    Speed 7 220
    Speed 9 180
    Weight 1 22
    Weight 3 32
    Weight 7 21
    Weight 10 33

    If I want to extract the newest I use something like this (made it in
    MS Access, so the syntax might differ slightly from SQLServer):

    SELECT table1.kpiID, table1.periodID , table1.Actual
    FROM table1 WHERE table1.periodID = (SELECT max(t.periodID) from
    table1 as t WHERE t.kpiID=table1. kpiID);

    BUT - how how do I get the second-newest period as well?

    Preferably I would like the final result to be a View with the
    following fields:
    kpiID, periodID_newest , Actual_newest, periodID_sec_ne west,
    Actual_sec_newe st

    Alternatively a View with 2 posts for each performace-indicator.

    Thanks in advance
    Ryan
  • Hugo Kornelis

    #2
    Re: Query/View: The 2 newest periods for each indicator

    On Fri, 24 Mar 2006 23:08:18 +0100, Ryan Dahl wrote:
    [color=blue]
    >Hi,
    >
    >I'm working on a simple performance-program, where I need to extract
    >information from the 2 newest periods for every performance-indicator
    >- And from there calculate a trend between these results.
    >
    >The problem is, that I can't find a simple way to extract the 2 latest
    >results.
    >
    >The Table (Table1) looks like this:
    >kpiID periodID Actual
    >Acceleration 2 3
    >Acceleration 5 4
    >Speed 1 100
    >Speed 4 200
    >Speed 7 220
    >Speed 9 180
    >Weight 1 22
    >Weight 3 32
    >Weight 7 21
    >Weight 10 33
    >
    >If I want to extract the newest I use something like this (made it in
    >MS Access, so the syntax might differ slightly from SQLServer):
    >
    >SELECT table1.kpiID, table1.periodID , table1.Actual
    >FROM table1 WHERE table1.periodID = (SELECT max(t.periodID) from
    >table1 as t WHERE t.kpiID=table1. kpiID);
    >
    >BUT - how how do I get the second-newest period as well?[/color]

    Hi Ryan,

    SELECT a.kpiID, a.periodID, a.Actual
    FROM table1 AS a
    WHERE (SELECT COUNT(*)
    FROM table1 AS b
    WHERE b.kpiID = a.kpiID
    AND b.periodID >= a.periodID) <= 2
    [color=blue]
    >
    >Preferably I would like the final result to be a View with the
    >following fields:
    >kpiID, periodID_newest , Actual_newest, periodID_sec_ne west,
    >Actual_sec_new est[/color]

    In that case, try this instead:

    SELECT a.kpiID, a.periodID, a.Actual, b.periodID, b.Actual
    FROM table1 AS a
    LEFT JOIN table1 AS b
    ON b.kpiID = a.kpiID
    AND b.periodID = (SELECT MAX(c.periodID)
    FROM table1 AS c
    WHERE c.kpiID = a.kpiID
    AND c.periodID < a.periodID)
    WHERE a.periodID = (SELECT MAX(t.periodID)
    FROM table1 AS t
    WHERE t.kpiID = a.kpiID)

    (Both queries above are untested - see www.aspfaq.com/5006 if you prefer
    a tested reply).

    --
    Hugo Kornelis, SQL Server MVP

    Comment

    • Ryan Dahl

      #3
      Re: Query/View: The 2 newest periods for each indicator

      Hi Hugo,

      Thanks a lot. I got them both working without any hassle.
      [color=blue]
      >SELECT a.kpiID, a.periodID, a.Actual
      >FROM table1 AS a
      >WHERE (SELECT COUNT(*)
      > FROM table1 AS b
      > WHERE b.kpiID = a.kpiID
      > AND b.periodID >= a.periodID) <= 2[/color]

      I find this to be quite clever - had to look at it some time to figure
      out how it works.
      [color=blue][color=green]
      >>
      >>Preferably I would like the final result to be a View with the
      >>following fields:
      >>kpiID, periodID_newest , Actual_newest, periodID_sec_ne west,
      >>Actual_sec_ne west[/color]
      >
      >In that case, try this instead:
      >
      >SELECT a.kpiID, a.periodID, a.Actual, b.periodID, b.Actual
      >FROM table1 AS a
      >LEFT JOIN table1 AS b
      > ON b.kpiID = a.kpiID
      > AND b.periodID = (SELECT MAX(c.periodID)
      > FROM table1 AS c
      > WHERE c.kpiID = a.kpiID
      > AND c.periodID < a.periodID)
      >WHERE a.periodID = (SELECT MAX(t.periodID)
      > FROM table1 AS t
      > WHERE t.kpiID = a.kpiID)
      >[/color]
      Works as well - minor adjustment needed: Move lines 5-8 to the end.

      Regards
      Ryan

      Comment

      • --CELKO--

        #4
        Re: Query/View: The 2 newest periods for each indicator

        Please post DDL, so that people do not have to guess what the keys,
        constraints, Declarative Referential Integrity, data types, etc. in
        your schema are. Sample data is also a good idea, along with clear
        specifications.

        I am a little confused on this. Aren't "accelerati on", "speed", and
        "weight" attributes and not values? Surely you are not mixing
        meteadata and data.

        Comment

        • Doug

          #5
          Re: Query/View: The 2 newest periods for each indicator

          celko, have you actually ever HELPED anyone on this list?????

          i'd be curious to review a link where your original SQL code, written
          in the past 10 years, is deomonstrated.

          thx,
          doug

          Comment

          • Hugo Kornelis

            #6
            Re: Query/View: The 2 newest periods for each indicator

            On Sat, 25 Mar 2006 08:21:38 +0100, Ryan Dahl wrote:
            [color=blue][color=green]
            >>SELECT a.kpiID, a.periodID, a.Actual, b.periodID, b.Actual
            >>FROM table1 AS a
            >>LEFT JOIN table1 AS b
            >> ON b.kpiID = a.kpiID
            >> AND b.periodID = (SELECT MAX(c.periodID)
            >> FROM table1 AS c
            >> WHERE c.kpiID = a.kpiID
            >> AND c.periodID < a.periodID)
            >>WHERE a.periodID = (SELECT MAX(t.periodID)
            >> FROM table1 AS t
            >> WHERE t.kpiID = a.kpiID)
            >>[/color]
            >Works as well - minor adjustment needed: Move lines 5-8 to the end.[/color]

            Hi Ryan,

            That changes the meaning of the query - the place where you put those
            lines dictates what will happen for a kpiID that has only one row.

            This one row is by definition the latest - but there's no second latest.
            If you use the query I suggested, you'll get this kpiID in your result,
            with it's only row as last measurement and NULLs as it's second latest
            measurement.

            Your version (after moving those rows) will exclude any kpiID with only
            one row. Only kpiIDs with two or more measurements will be displayed. If
            that is indeed your requirement, then you can safely move these lines.
            And you can change the LEFT JOIN in an INNER JOIN as well, to get some
            performance gain.

            --
            Hugo Kornelis, SQL Server MVP

            Comment

            • Ryan Dahl

              #7
              Re: Query/View: The 2 newest periods for each indicator

              On Mon, 27 Mar 2006 23:48:50 +0200, Hugo Kornelis
              <hugo@perFact.R EMOVETHIS.info. INVALID> wrote:
              [color=blue]
              >On Sat, 25 Mar 2006 08:21:38 +0100, Ryan Dahl wrote:
              >[color=green][color=darkred]
              >>>SELECT a.kpiID, a.periodID, a.Actual, b.periodID, b.Actual
              >>>FROM table1 AS a
              >>>LEFT JOIN table1 AS b
              >>> ON b.kpiID = a.kpiID
              >>> AND b.periodID = (SELECT MAX(c.periodID)
              >>> FROM table1 AS c
              >>> WHERE c.kpiID = a.kpiID
              >>> AND c.periodID < a.periodID)
              >>>WHERE a.periodID = (SELECT MAX(t.periodID)
              >>> FROM table1 AS t
              >>> WHERE t.kpiID = a.kpiID)
              >>>[/color]
              >>Works as well - minor adjustment needed: Move lines 5-8 to the end.[/color]
              >
              >Hi Ryan,
              >
              >That changes the meaning of the query - the place where you put those
              >lines dictates what will happen for a kpiID that has only one row.
              >
              >This one row is by definition the latest - but there's no second latest.
              >If you use the query I suggested, you'll get this kpiID in your result,
              >with it's only row as last measurement and NULLs as it's second latest
              >measurement.
              >
              >Your version (after moving those rows) will exclude any kpiID with only
              >one row. Only kpiIDs with two or more measurements will be displayed. If
              >that is indeed your requirement, then you can safely move these lines.
              >And you can change the LEFT JOIN in an INNER JOIN as well, to get some
              >performance gain.[/color]

              Hi Hugo,

              thanks for pointing this out. SQLServer accepted without any problems.
              As mentioned earlier I tested on MS Access, and it seems that it
              doesn't support this join-type (no error-description of any kind) so I
              made the mistake of assuming there was a small error in the
              sql-string.

              Thanks again.
              Ryan

              Comment

              • qtuner@gmail.com

                #8
                Re: Query/View: The 2 newest periods for each indicator

                I've read 2 books written by joe celko, and and both have really helped
                me. I frequently profile my code to see what it is doing. So he's
                helped me.

                Comment

                • --CELKO--

                  #9
                  Re: Query/View: The 2 newest periods for each indicator

                  Go to the CMP archives for DBMS, DATABASE PROGRAMMING & DESIGN, and
                  INTELLIGENT ENTERPRISE magazines to go back over ten years. I have
                  written over 750 columns in the computer trade and academic press,
                  mostly dealing with data and databases. I currently write for BMC's
                  DBAzine.com e-magazine.

                  My six books: SQL FOR SMARTIES (Morgan-Kaufmann, 1995, second edition
                  1999, third edition 2005), SQL PUZZLES & ANSWERS (Morgan-Kaufmann,
                  1997), DATA & DATABASES (Morgan-Kaufmann, 1999) and TREES & HIERARCHIES
                  IN SQL (Morgan-Kaufmann, 2004) and SQL PROGRAMMING STYLE
                  Morgan-Kaufmann, 2005).
                  Past magazine columns include: "SQL Explorer" in DBMS (Miller-Freeman);
                  "Celko on SQL" in DATABASE PROGRAMMING & DESIGN (Miller-Freeman);
                  "WATCOM SQL Corner" in POWERBUILDER DEVELOPERS' JOURNAL (SysCon); "SQL
                  Puzzle" in BOXES & ARROWS (Frank Sweet Publishing); "DBMS/Report" in
                  SYSTEMS INTEGRATION (Cahner-Ziff); "Data Desk" in TECH SPECIALIST
                  (R&D); "Data Points" in PC TECHNIQUES (Coriolis Group); "Celko on
                  Software" in COMPUTING (VNC Publications, UK), "SELECT * FROM Austin"
                  (Array Publications, The Netherlands), and he was editor for the
                  "Puzzles & Problems" section of ABACUS (Springer-Verlag) and I ran the
                  CASEFORUM section 18, "Celko on SQL", on CompuServe.

                  So, what have you done?

                  Comment

                  • Alexander Kuznetsov

                    #10
                    Re: Query/View: The 2 newest periods for each indicator

                    if it is SQL Server 2005, use row_number() *untested*:

                    select * from(
                    SELECT table1.kpiID, table1.periodID , table1.Actual,
                    row_number() over(partition by kpId order by periodId desc) rn
                    FROM table1
                    ) t
                    where rn<3

                    Comment

                    • GeorgeM

                      #11
                      Re: Query/View: The 2 newest periods for each indicator

                      That's Joe Celko, the demi-god of SQL for pete's sake.

                      Comment

                      Working...