How to get the last not-null value in an ordered column of a huge table? Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)Quickly change NULL column to NOT NULLTSQL change column constraint between null and not nullHow to get the first or last row in ordered result set, depending by column value?Can I use SPARSE somehow on a non-nullable bit column with mostly false values?Columnstore Aggregate Pushdown doesn't work for float/real data typesHow to handle null value number DataWarehouseHow to get 0 in the null value fieldsHOW to work with NULL in a NOT NULL column?How to select the set of last non-NULL values per column over a group?Select last non-null value for given partition - Postgres 10

Fishing simulator

How to politely respond to generic emails requesting a PhD/job in my lab? Without wasting too much time

Need a suitable toxic chemical for a murder plot in my novel

Limit for e and 1/e

Did the new image of black hole confirm the general theory of relativity?

Is there folklore associating late breastfeeding with low intelligence and/or gullibility?

Stopping real property loss from eroding embankment

Why does tar appear to skip file contents when output file is /dev/null?

Problem when applying foreach loop

How to say that you spent the night with someone, you were only sleeping and nothing else?

Is above average number of years spent on PhD considered a red flag in future academia or industry positions?

Can I throw a longsword at someone?

How do you clear the ApexPages.getMessages() collection in a test?

Stop battery usage [Ubuntu 18]

What items from the Roman-age tech-level could be used to deter all creatures from entering a small area?

What is the order of Mitzvot in Rambam's Sefer Hamitzvot?

What's the point in a preamp?

Can a zero nonce be safely used with AES-GCM if the key is random and never used again?

What LEGO pieces have "real-world" functionality?

I'm thinking of a number

I'm having difficulty getting my players to do stuff in a sandbox campaign

Why is there no army of Iron-Mans in the MCU?

Windows 10: How to Lock (not sleep) laptop on lid close?

How is simplicity better than precision and clarity in prose?



How to get the last not-null value in an ordered column of a huge table?



Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)Quickly change NULL column to NOT NULLTSQL change column constraint between null and not nullHow to get the first or last row in ordered result set, depending by column value?Can I use SPARSE somehow on a non-nullable bit column with mostly false values?Columnstore Aggregate Pushdown doesn't work for float/real data typesHow to handle null value number DataWarehouseHow to get 0 in the null value fieldsHOW to work with NULL in a NOT NULL column?How to select the set of last non-NULL values per column over a group?Select last non-null value for given partition - Postgres 10



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








9















I have the following input:



 id | value 
----+-------
1 | 136
2 | NULL
3 | 650
4 | NULL
5 | NULL
6 | NULL
7 | 954
8 | NULL
9 | 104
10 | NULL


I expect the following result:



 id | value 
----+-------
1 | 136
2 | 136
3 | 650
4 | 650
5 | 650
6 | 650
7 | 954
8 | 954
9 | 104
10 | 104


The trivial solution would be join the tables with a < relation, and then selecting the MAX value in a GROUP BY:



WITH tmp AS (
SELECT t2.id, MAX(t1.id) AS lastKnownId
FROM t t1, t t2
WHERE
t1.value IS NOT NULL
AND
t2.id >= t1.id
GROUP BY t2.id
)
SELECT
tmp.id, t.value
FROM t, tmp
WHERE t.id = tmp.lastKnownId;


However, the trivial execution of this code would create internally the square of the count of the rows of the input table ( O(n^2) ). I expected t-sql to optimize it out - on a block/record level, the task to do is very easy and linear, essentially a for loop ( O(n) ).



However, on my experiments, the latest MS SQL 2016 can't optimize this query correctly, making this query impossible to execute for a large input table.



Furthermore, the query has to run quickly, making a similarly easy (but very different) cursor-based solution infeasible.



Using some memory-backed temporary table could be a good compromise, but I am not sure if it can be run significantly quicker, considered that my example query using subqueries didn't work.



I am also thinking on to dig out some windowing function from the t-sql docs, what could be tricked to do what I want. For example, cumulative sum is doing some very similar, but I couldn't trick it to give the latest non-null element, and not the sum of the elements before.



The ideal solution would be a quick query without procedural code or temporary tables. Alternatively, also a solution with temporary tables is okay, but iterating the table procedurally is not.










share|improve this question






























    9















    I have the following input:



     id | value 
    ----+-------
    1 | 136
    2 | NULL
    3 | 650
    4 | NULL
    5 | NULL
    6 | NULL
    7 | 954
    8 | NULL
    9 | 104
    10 | NULL


    I expect the following result:



     id | value 
    ----+-------
    1 | 136
    2 | 136
    3 | 650
    4 | 650
    5 | 650
    6 | 650
    7 | 954
    8 | 954
    9 | 104
    10 | 104


    The trivial solution would be join the tables with a < relation, and then selecting the MAX value in a GROUP BY:



    WITH tmp AS (
    SELECT t2.id, MAX(t1.id) AS lastKnownId
    FROM t t1, t t2
    WHERE
    t1.value IS NOT NULL
    AND
    t2.id >= t1.id
    GROUP BY t2.id
    )
    SELECT
    tmp.id, t.value
    FROM t, tmp
    WHERE t.id = tmp.lastKnownId;


    However, the trivial execution of this code would create internally the square of the count of the rows of the input table ( O(n^2) ). I expected t-sql to optimize it out - on a block/record level, the task to do is very easy and linear, essentially a for loop ( O(n) ).



    However, on my experiments, the latest MS SQL 2016 can't optimize this query correctly, making this query impossible to execute for a large input table.



    Furthermore, the query has to run quickly, making a similarly easy (but very different) cursor-based solution infeasible.



    Using some memory-backed temporary table could be a good compromise, but I am not sure if it can be run significantly quicker, considered that my example query using subqueries didn't work.



    I am also thinking on to dig out some windowing function from the t-sql docs, what could be tricked to do what I want. For example, cumulative sum is doing some very similar, but I couldn't trick it to give the latest non-null element, and not the sum of the elements before.



    The ideal solution would be a quick query without procedural code or temporary tables. Alternatively, also a solution with temporary tables is okay, but iterating the table procedurally is not.










    share|improve this question


























      9












      9








      9


      1






      I have the following input:



       id | value 
      ----+-------
      1 | 136
      2 | NULL
      3 | 650
      4 | NULL
      5 | NULL
      6 | NULL
      7 | 954
      8 | NULL
      9 | 104
      10 | NULL


      I expect the following result:



       id | value 
      ----+-------
      1 | 136
      2 | 136
      3 | 650
      4 | 650
      5 | 650
      6 | 650
      7 | 954
      8 | 954
      9 | 104
      10 | 104


      The trivial solution would be join the tables with a < relation, and then selecting the MAX value in a GROUP BY:



      WITH tmp AS (
      SELECT t2.id, MAX(t1.id) AS lastKnownId
      FROM t t1, t t2
      WHERE
      t1.value IS NOT NULL
      AND
      t2.id >= t1.id
      GROUP BY t2.id
      )
      SELECT
      tmp.id, t.value
      FROM t, tmp
      WHERE t.id = tmp.lastKnownId;


      However, the trivial execution of this code would create internally the square of the count of the rows of the input table ( O(n^2) ). I expected t-sql to optimize it out - on a block/record level, the task to do is very easy and linear, essentially a for loop ( O(n) ).



      However, on my experiments, the latest MS SQL 2016 can't optimize this query correctly, making this query impossible to execute for a large input table.



      Furthermore, the query has to run quickly, making a similarly easy (but very different) cursor-based solution infeasible.



      Using some memory-backed temporary table could be a good compromise, but I am not sure if it can be run significantly quicker, considered that my example query using subqueries didn't work.



      I am also thinking on to dig out some windowing function from the t-sql docs, what could be tricked to do what I want. For example, cumulative sum is doing some very similar, but I couldn't trick it to give the latest non-null element, and not the sum of the elements before.



      The ideal solution would be a quick query without procedural code or temporary tables. Alternatively, also a solution with temporary tables is okay, but iterating the table procedurally is not.










      share|improve this question
















      I have the following input:



       id | value 
      ----+-------
      1 | 136
      2 | NULL
      3 | 650
      4 | NULL
      5 | NULL
      6 | NULL
      7 | 954
      8 | NULL
      9 | 104
      10 | NULL


      I expect the following result:



       id | value 
      ----+-------
      1 | 136
      2 | 136
      3 | 650
      4 | 650
      5 | 650
      6 | 650
      7 | 954
      8 | 954
      9 | 104
      10 | 104


      The trivial solution would be join the tables with a < relation, and then selecting the MAX value in a GROUP BY:



      WITH tmp AS (
      SELECT t2.id, MAX(t1.id) AS lastKnownId
      FROM t t1, t t2
      WHERE
      t1.value IS NOT NULL
      AND
      t2.id >= t1.id
      GROUP BY t2.id
      )
      SELECT
      tmp.id, t.value
      FROM t, tmp
      WHERE t.id = tmp.lastKnownId;


      However, the trivial execution of this code would create internally the square of the count of the rows of the input table ( O(n^2) ). I expected t-sql to optimize it out - on a block/record level, the task to do is very easy and linear, essentially a for loop ( O(n) ).



      However, on my experiments, the latest MS SQL 2016 can't optimize this query correctly, making this query impossible to execute for a large input table.



      Furthermore, the query has to run quickly, making a similarly easy (but very different) cursor-based solution infeasible.



      Using some memory-backed temporary table could be a good compromise, but I am not sure if it can be run significantly quicker, considered that my example query using subqueries didn't work.



      I am also thinking on to dig out some windowing function from the t-sql docs, what could be tricked to do what I want. For example, cumulative sum is doing some very similar, but I couldn't trick it to give the latest non-null element, and not the sum of the elements before.



      The ideal solution would be a quick query without procedural code or temporary tables. Alternatively, also a solution with temporary tables is okay, but iterating the table procedurally is not.







      sql-server t-sql null window-functions running-totals






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Apr 3 at 3:17









      Paul White

      54.2k14288461




      54.2k14288461










      asked Mar 31 at 17:19









      peterhpeterh

      1,13341532




      1,13341532




















          3 Answers
          3






          active

          oldest

          votes


















          11














          A common solution to this type of problem is given by Itzik Ben-Gan in his article The Last non NULL Puzzle:



          DROP TABLE IF EXISTS dbo.Example;

          CREATE TABLE dbo.Example
          (
          id integer PRIMARY KEY,
          val integer NULL
          );

          INSERT dbo.Example
          (id, val)
          VALUES
          (1, 136),
          (2, NULL),
          (3, 650),
          (4, NULL),
          (5, NULL),
          (6, NULL),
          (7, 954),
          (8, NULL),
          (9, 104),
          (10, NULL);

          SELECT
          E.id,
          E.val,
          lastval =
          CAST(
          SUBSTRING(
          MAX(CAST(E.id AS binary(4)) + CAST(E.val AS binary(4))) OVER (
          ORDER BY E.id
          ROWS UNBOUNDED PRECEDING),
          5, 4)
          AS integer)
          FROM dbo.Example AS E
          ORDER BY
          E.id;


          Demo: db<>fiddle






          share|improve this answer






























            9















            I expected t-sql to optimize it out - on a block/record level, the
            task to do is very easy and linear, essentially a for loop ( O(n) ).




            That's not the query that you wrote. It may not be equivalent to the query that you wrote depending on some otherwise minor detail of the table schema. You're expecting too much from the query optimizer.



            With the right indexing you can get the algorithm that you seek through the following T-SQL:



            SELECT t1.id, ca.[VALUE] 
            FROM dbo.[BIG_TABLE(FOR_U)] t1
            CROSS APPLY (
            SELECT TOP (1) [VALUE]
            FROM dbo.[BIG_TABLE(FOR_U)] t2
            WHERE t2.ID <= t1.ID AND t2.[VALUE] IS NOT NULL
            ORDER BY t2.ID DESC
            ) ca; --ORDER BY t1.ID ASC


            For each row, the query processor traverses the index backwards and stops when it finds a row with a non null value for [VALUE]. On my machine this finishes in about 90 seconds for 100 million rows in the source table. The query runs longer than necessary because some amount of time is wasted on the client discarding all of those rows.



            It's not clear to me if you need ordered results or what you plan on doing with such a large result set. The query can be adjusted to meet the actual scenario. The biggest advantage of this approach is that it does not require a sort in the query plan. That can help for larger result sets. One disadvantage is that performance will not be optimal if there are a lot of NULLs in the table because many rows will be read from the index and discarded. You should be able to improve performance with a filtered index that excludes NULLs for that case.



            Sample data for the test:



            DROP TABLE IF EXISTS #t;

            CREATE TABLE #t (
            ID BIGINT NOT NULL
            );

            INSERT INTO #t WITH (TABLOCK)
            SELECT TOP (10000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1
            FROM master..spt_values t1
            CROSS JOIN master..spt_values t2
            OPTION (MAXDOP 1);

            DROP TABLE IF EXISTS dbo.[BIG_TABLE(FOR_U)];

            CREATE TABLE dbo.[BIG_TABLE(FOR_U)] (
            ID BIGINT NOT NULL,
            [VALUE] BIGINT NULL
            );

            INSERT INTO dbo.[BIG_TABLE(FOR_U)] WITH (TABLOCK)
            SELECT 10000 * t1.ID + t2.ID, CASE WHEN (t1.ID + t2.ID) % 3 = 1 THEN t2.ID ELSE NULL END
            FROM #t t1
            CROSS JOIN #t t2;

            CREATE UNIQUE CLUSTERED INDEX ADD_ORDERING ON dbo.[BIG_TABLE(FOR_U)] (ID);





            share|improve this answer























            • Thanks the answer! I have missing data in my input, I need to approximate them based on the last known value. The ratio of the not-NULLs is between 0.1% and 1%, I have around 100million records, the latest recent hardware, and mssql 2016.

              – peterh
              Apr 1 at 2:57











            • I used a simple naive queries, without any (indexed) temporary tables, with WITH ... AS constructs. I am happy that ms sql can optimize it if it got enough advices. I am experimenting on.

              – peterh
              Apr 1 at 13:04











            • @peterh: To restate, in your real data about 99% of the rows have a NULLfor [value]?

              – Joe Obbish
              Apr 1 at 22:49











            • Yes. Maybe 99.9. In the real data, also the "value"s are growing with the ids, if it helps.

              – peterh
              Apr 2 at 6:11


















            7














            One method, by using OVER() and MAX() and COUNT() based on this source could be:



            SELECT ID, MAX(value) OVER (PARTITION BY Value2) as value
            FROM
            (
            SELECT ID, value
            ,COUNT(value) OVER (ORDER BY ID) AS Value2
            FROM dbo.HugeTable
            ) a
            ORDER BY ID;


            Result



            Id UpdatedValue
            1 136
            2 136
            3 650
            4 650
            5 650
            6 650
            7 954
            8 954
            9 104
            10 104



            Another method based on this source, closely related to the first example



            ;WITH CTE As 
            (
            SELECT value,
            Id,
            COUNT(value)
            OVER(ORDER BY Id) As Value2
            FROM dbo.HugeTable
            ),

            CTE2 AS (
            SELECT Id,
            value,
            First_Value(value)
            OVER( PARTITION BY Value2
            ORDER BY Id) As UpdatedValue
            FROM CTE
            )
            SELECT Id,UpdatedValue
            FROM CTE2;





            share|improve this answer




















            • 3





              Consider adding details about how these approaches perform with a "huge table".

              – Joe Obbish
              Mar 31 at 22:32











            • Thanks! This is what I finally did, although not COUNT()... OVER, instead MAX(). It became much faster, but it is still slow. Be back soon.

              – peterh
              Apr 1 at 3:02












            Your Answer








            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "182"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f233610%2fhow-to-get-the-last-not-null-value-in-an-ordered-column-of-a-huge-table%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            11














            A common solution to this type of problem is given by Itzik Ben-Gan in his article The Last non NULL Puzzle:



            DROP TABLE IF EXISTS dbo.Example;

            CREATE TABLE dbo.Example
            (
            id integer PRIMARY KEY,
            val integer NULL
            );

            INSERT dbo.Example
            (id, val)
            VALUES
            (1, 136),
            (2, NULL),
            (3, 650),
            (4, NULL),
            (5, NULL),
            (6, NULL),
            (7, 954),
            (8, NULL),
            (9, 104),
            (10, NULL);

            SELECT
            E.id,
            E.val,
            lastval =
            CAST(
            SUBSTRING(
            MAX(CAST(E.id AS binary(4)) + CAST(E.val AS binary(4))) OVER (
            ORDER BY E.id
            ROWS UNBOUNDED PRECEDING),
            5, 4)
            AS integer)
            FROM dbo.Example AS E
            ORDER BY
            E.id;


            Demo: db<>fiddle






            share|improve this answer



























              11














              A common solution to this type of problem is given by Itzik Ben-Gan in his article The Last non NULL Puzzle:



              DROP TABLE IF EXISTS dbo.Example;

              CREATE TABLE dbo.Example
              (
              id integer PRIMARY KEY,
              val integer NULL
              );

              INSERT dbo.Example
              (id, val)
              VALUES
              (1, 136),
              (2, NULL),
              (3, 650),
              (4, NULL),
              (5, NULL),
              (6, NULL),
              (7, 954),
              (8, NULL),
              (9, 104),
              (10, NULL);

              SELECT
              E.id,
              E.val,
              lastval =
              CAST(
              SUBSTRING(
              MAX(CAST(E.id AS binary(4)) + CAST(E.val AS binary(4))) OVER (
              ORDER BY E.id
              ROWS UNBOUNDED PRECEDING),
              5, 4)
              AS integer)
              FROM dbo.Example AS E
              ORDER BY
              E.id;


              Demo: db<>fiddle






              share|improve this answer

























                11












                11








                11







                A common solution to this type of problem is given by Itzik Ben-Gan in his article The Last non NULL Puzzle:



                DROP TABLE IF EXISTS dbo.Example;

                CREATE TABLE dbo.Example
                (
                id integer PRIMARY KEY,
                val integer NULL
                );

                INSERT dbo.Example
                (id, val)
                VALUES
                (1, 136),
                (2, NULL),
                (3, 650),
                (4, NULL),
                (5, NULL),
                (6, NULL),
                (7, 954),
                (8, NULL),
                (9, 104),
                (10, NULL);

                SELECT
                E.id,
                E.val,
                lastval =
                CAST(
                SUBSTRING(
                MAX(CAST(E.id AS binary(4)) + CAST(E.val AS binary(4))) OVER (
                ORDER BY E.id
                ROWS UNBOUNDED PRECEDING),
                5, 4)
                AS integer)
                FROM dbo.Example AS E
                ORDER BY
                E.id;


                Demo: db<>fiddle






                share|improve this answer













                A common solution to this type of problem is given by Itzik Ben-Gan in his article The Last non NULL Puzzle:



                DROP TABLE IF EXISTS dbo.Example;

                CREATE TABLE dbo.Example
                (
                id integer PRIMARY KEY,
                val integer NULL
                );

                INSERT dbo.Example
                (id, val)
                VALUES
                (1, 136),
                (2, NULL),
                (3, 650),
                (4, NULL),
                (5, NULL),
                (6, NULL),
                (7, 954),
                (8, NULL),
                (9, 104),
                (10, NULL);

                SELECT
                E.id,
                E.val,
                lastval =
                CAST(
                SUBSTRING(
                MAX(CAST(E.id AS binary(4)) + CAST(E.val AS binary(4))) OVER (
                ORDER BY E.id
                ROWS UNBOUNDED PRECEDING),
                5, 4)
                AS integer)
                FROM dbo.Example AS E
                ORDER BY
                E.id;


                Demo: db<>fiddle







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Apr 1 at 0:30









                Paul WhitePaul White

                54.2k14288461




                54.2k14288461























                    9















                    I expected t-sql to optimize it out - on a block/record level, the
                    task to do is very easy and linear, essentially a for loop ( O(n) ).




                    That's not the query that you wrote. It may not be equivalent to the query that you wrote depending on some otherwise minor detail of the table schema. You're expecting too much from the query optimizer.



                    With the right indexing you can get the algorithm that you seek through the following T-SQL:



                    SELECT t1.id, ca.[VALUE] 
                    FROM dbo.[BIG_TABLE(FOR_U)] t1
                    CROSS APPLY (
                    SELECT TOP (1) [VALUE]
                    FROM dbo.[BIG_TABLE(FOR_U)] t2
                    WHERE t2.ID <= t1.ID AND t2.[VALUE] IS NOT NULL
                    ORDER BY t2.ID DESC
                    ) ca; --ORDER BY t1.ID ASC


                    For each row, the query processor traverses the index backwards and stops when it finds a row with a non null value for [VALUE]. On my machine this finishes in about 90 seconds for 100 million rows in the source table. The query runs longer than necessary because some amount of time is wasted on the client discarding all of those rows.



                    It's not clear to me if you need ordered results or what you plan on doing with such a large result set. The query can be adjusted to meet the actual scenario. The biggest advantage of this approach is that it does not require a sort in the query plan. That can help for larger result sets. One disadvantage is that performance will not be optimal if there are a lot of NULLs in the table because many rows will be read from the index and discarded. You should be able to improve performance with a filtered index that excludes NULLs for that case.



                    Sample data for the test:



                    DROP TABLE IF EXISTS #t;

                    CREATE TABLE #t (
                    ID BIGINT NOT NULL
                    );

                    INSERT INTO #t WITH (TABLOCK)
                    SELECT TOP (10000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1
                    FROM master..spt_values t1
                    CROSS JOIN master..spt_values t2
                    OPTION (MAXDOP 1);

                    DROP TABLE IF EXISTS dbo.[BIG_TABLE(FOR_U)];

                    CREATE TABLE dbo.[BIG_TABLE(FOR_U)] (
                    ID BIGINT NOT NULL,
                    [VALUE] BIGINT NULL
                    );

                    INSERT INTO dbo.[BIG_TABLE(FOR_U)] WITH (TABLOCK)
                    SELECT 10000 * t1.ID + t2.ID, CASE WHEN (t1.ID + t2.ID) % 3 = 1 THEN t2.ID ELSE NULL END
                    FROM #t t1
                    CROSS JOIN #t t2;

                    CREATE UNIQUE CLUSTERED INDEX ADD_ORDERING ON dbo.[BIG_TABLE(FOR_U)] (ID);





                    share|improve this answer























                    • Thanks the answer! I have missing data in my input, I need to approximate them based on the last known value. The ratio of the not-NULLs is between 0.1% and 1%, I have around 100million records, the latest recent hardware, and mssql 2016.

                      – peterh
                      Apr 1 at 2:57











                    • I used a simple naive queries, without any (indexed) temporary tables, with WITH ... AS constructs. I am happy that ms sql can optimize it if it got enough advices. I am experimenting on.

                      – peterh
                      Apr 1 at 13:04











                    • @peterh: To restate, in your real data about 99% of the rows have a NULLfor [value]?

                      – Joe Obbish
                      Apr 1 at 22:49











                    • Yes. Maybe 99.9. In the real data, also the "value"s are growing with the ids, if it helps.

                      – peterh
                      Apr 2 at 6:11















                    9















                    I expected t-sql to optimize it out - on a block/record level, the
                    task to do is very easy and linear, essentially a for loop ( O(n) ).




                    That's not the query that you wrote. It may not be equivalent to the query that you wrote depending on some otherwise minor detail of the table schema. You're expecting too much from the query optimizer.



                    With the right indexing you can get the algorithm that you seek through the following T-SQL:



                    SELECT t1.id, ca.[VALUE] 
                    FROM dbo.[BIG_TABLE(FOR_U)] t1
                    CROSS APPLY (
                    SELECT TOP (1) [VALUE]
                    FROM dbo.[BIG_TABLE(FOR_U)] t2
                    WHERE t2.ID <= t1.ID AND t2.[VALUE] IS NOT NULL
                    ORDER BY t2.ID DESC
                    ) ca; --ORDER BY t1.ID ASC


                    For each row, the query processor traverses the index backwards and stops when it finds a row with a non null value for [VALUE]. On my machine this finishes in about 90 seconds for 100 million rows in the source table. The query runs longer than necessary because some amount of time is wasted on the client discarding all of those rows.



                    It's not clear to me if you need ordered results or what you plan on doing with such a large result set. The query can be adjusted to meet the actual scenario. The biggest advantage of this approach is that it does not require a sort in the query plan. That can help for larger result sets. One disadvantage is that performance will not be optimal if there are a lot of NULLs in the table because many rows will be read from the index and discarded. You should be able to improve performance with a filtered index that excludes NULLs for that case.



                    Sample data for the test:



                    DROP TABLE IF EXISTS #t;

                    CREATE TABLE #t (
                    ID BIGINT NOT NULL
                    );

                    INSERT INTO #t WITH (TABLOCK)
                    SELECT TOP (10000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1
                    FROM master..spt_values t1
                    CROSS JOIN master..spt_values t2
                    OPTION (MAXDOP 1);

                    DROP TABLE IF EXISTS dbo.[BIG_TABLE(FOR_U)];

                    CREATE TABLE dbo.[BIG_TABLE(FOR_U)] (
                    ID BIGINT NOT NULL,
                    [VALUE] BIGINT NULL
                    );

                    INSERT INTO dbo.[BIG_TABLE(FOR_U)] WITH (TABLOCK)
                    SELECT 10000 * t1.ID + t2.ID, CASE WHEN (t1.ID + t2.ID) % 3 = 1 THEN t2.ID ELSE NULL END
                    FROM #t t1
                    CROSS JOIN #t t2;

                    CREATE UNIQUE CLUSTERED INDEX ADD_ORDERING ON dbo.[BIG_TABLE(FOR_U)] (ID);





                    share|improve this answer























                    • Thanks the answer! I have missing data in my input, I need to approximate them based on the last known value. The ratio of the not-NULLs is between 0.1% and 1%, I have around 100million records, the latest recent hardware, and mssql 2016.

                      – peterh
                      Apr 1 at 2:57











                    • I used a simple naive queries, without any (indexed) temporary tables, with WITH ... AS constructs. I am happy that ms sql can optimize it if it got enough advices. I am experimenting on.

                      – peterh
                      Apr 1 at 13:04











                    • @peterh: To restate, in your real data about 99% of the rows have a NULLfor [value]?

                      – Joe Obbish
                      Apr 1 at 22:49











                    • Yes. Maybe 99.9. In the real data, also the "value"s are growing with the ids, if it helps.

                      – peterh
                      Apr 2 at 6:11













                    9












                    9








                    9








                    I expected t-sql to optimize it out - on a block/record level, the
                    task to do is very easy and linear, essentially a for loop ( O(n) ).




                    That's not the query that you wrote. It may not be equivalent to the query that you wrote depending on some otherwise minor detail of the table schema. You're expecting too much from the query optimizer.



                    With the right indexing you can get the algorithm that you seek through the following T-SQL:



                    SELECT t1.id, ca.[VALUE] 
                    FROM dbo.[BIG_TABLE(FOR_U)] t1
                    CROSS APPLY (
                    SELECT TOP (1) [VALUE]
                    FROM dbo.[BIG_TABLE(FOR_U)] t2
                    WHERE t2.ID <= t1.ID AND t2.[VALUE] IS NOT NULL
                    ORDER BY t2.ID DESC
                    ) ca; --ORDER BY t1.ID ASC


                    For each row, the query processor traverses the index backwards and stops when it finds a row with a non null value for [VALUE]. On my machine this finishes in about 90 seconds for 100 million rows in the source table. The query runs longer than necessary because some amount of time is wasted on the client discarding all of those rows.



                    It's not clear to me if you need ordered results or what you plan on doing with such a large result set. The query can be adjusted to meet the actual scenario. The biggest advantage of this approach is that it does not require a sort in the query plan. That can help for larger result sets. One disadvantage is that performance will not be optimal if there are a lot of NULLs in the table because many rows will be read from the index and discarded. You should be able to improve performance with a filtered index that excludes NULLs for that case.



                    Sample data for the test:



                    DROP TABLE IF EXISTS #t;

                    CREATE TABLE #t (
                    ID BIGINT NOT NULL
                    );

                    INSERT INTO #t WITH (TABLOCK)
                    SELECT TOP (10000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1
                    FROM master..spt_values t1
                    CROSS JOIN master..spt_values t2
                    OPTION (MAXDOP 1);

                    DROP TABLE IF EXISTS dbo.[BIG_TABLE(FOR_U)];

                    CREATE TABLE dbo.[BIG_TABLE(FOR_U)] (
                    ID BIGINT NOT NULL,
                    [VALUE] BIGINT NULL
                    );

                    INSERT INTO dbo.[BIG_TABLE(FOR_U)] WITH (TABLOCK)
                    SELECT 10000 * t1.ID + t2.ID, CASE WHEN (t1.ID + t2.ID) % 3 = 1 THEN t2.ID ELSE NULL END
                    FROM #t t1
                    CROSS JOIN #t t2;

                    CREATE UNIQUE CLUSTERED INDEX ADD_ORDERING ON dbo.[BIG_TABLE(FOR_U)] (ID);





                    share|improve this answer














                    I expected t-sql to optimize it out - on a block/record level, the
                    task to do is very easy and linear, essentially a for loop ( O(n) ).




                    That's not the query that you wrote. It may not be equivalent to the query that you wrote depending on some otherwise minor detail of the table schema. You're expecting too much from the query optimizer.



                    With the right indexing you can get the algorithm that you seek through the following T-SQL:



                    SELECT t1.id, ca.[VALUE] 
                    FROM dbo.[BIG_TABLE(FOR_U)] t1
                    CROSS APPLY (
                    SELECT TOP (1) [VALUE]
                    FROM dbo.[BIG_TABLE(FOR_U)] t2
                    WHERE t2.ID <= t1.ID AND t2.[VALUE] IS NOT NULL
                    ORDER BY t2.ID DESC
                    ) ca; --ORDER BY t1.ID ASC


                    For each row, the query processor traverses the index backwards and stops when it finds a row with a non null value for [VALUE]. On my machine this finishes in about 90 seconds for 100 million rows in the source table. The query runs longer than necessary because some amount of time is wasted on the client discarding all of those rows.



                    It's not clear to me if you need ordered results or what you plan on doing with such a large result set. The query can be adjusted to meet the actual scenario. The biggest advantage of this approach is that it does not require a sort in the query plan. That can help for larger result sets. One disadvantage is that performance will not be optimal if there are a lot of NULLs in the table because many rows will be read from the index and discarded. You should be able to improve performance with a filtered index that excludes NULLs for that case.



                    Sample data for the test:



                    DROP TABLE IF EXISTS #t;

                    CREATE TABLE #t (
                    ID BIGINT NOT NULL
                    );

                    INSERT INTO #t WITH (TABLOCK)
                    SELECT TOP (10000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1
                    FROM master..spt_values t1
                    CROSS JOIN master..spt_values t2
                    OPTION (MAXDOP 1);

                    DROP TABLE IF EXISTS dbo.[BIG_TABLE(FOR_U)];

                    CREATE TABLE dbo.[BIG_TABLE(FOR_U)] (
                    ID BIGINT NOT NULL,
                    [VALUE] BIGINT NULL
                    );

                    INSERT INTO dbo.[BIG_TABLE(FOR_U)] WITH (TABLOCK)
                    SELECT 10000 * t1.ID + t2.ID, CASE WHEN (t1.ID + t2.ID) % 3 = 1 THEN t2.ID ELSE NULL END
                    FROM #t t1
                    CROSS JOIN #t t2;

                    CREATE UNIQUE CLUSTERED INDEX ADD_ORDERING ON dbo.[BIG_TABLE(FOR_U)] (ID);






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Mar 31 at 22:31









                    Joe ObbishJoe Obbish

                    21.9k43291




                    21.9k43291












                    • Thanks the answer! I have missing data in my input, I need to approximate them based on the last known value. The ratio of the not-NULLs is between 0.1% and 1%, I have around 100million records, the latest recent hardware, and mssql 2016.

                      – peterh
                      Apr 1 at 2:57











                    • I used a simple naive queries, without any (indexed) temporary tables, with WITH ... AS constructs. I am happy that ms sql can optimize it if it got enough advices. I am experimenting on.

                      – peterh
                      Apr 1 at 13:04











                    • @peterh: To restate, in your real data about 99% of the rows have a NULLfor [value]?

                      – Joe Obbish
                      Apr 1 at 22:49











                    • Yes. Maybe 99.9. In the real data, also the "value"s are growing with the ids, if it helps.

                      – peterh
                      Apr 2 at 6:11

















                    • Thanks the answer! I have missing data in my input, I need to approximate them based on the last known value. The ratio of the not-NULLs is between 0.1% and 1%, I have around 100million records, the latest recent hardware, and mssql 2016.

                      – peterh
                      Apr 1 at 2:57











                    • I used a simple naive queries, without any (indexed) temporary tables, with WITH ... AS constructs. I am happy that ms sql can optimize it if it got enough advices. I am experimenting on.

                      – peterh
                      Apr 1 at 13:04











                    • @peterh: To restate, in your real data about 99% of the rows have a NULLfor [value]?

                      – Joe Obbish
                      Apr 1 at 22:49











                    • Yes. Maybe 99.9. In the real data, also the "value"s are growing with the ids, if it helps.

                      – peterh
                      Apr 2 at 6:11
















                    Thanks the answer! I have missing data in my input, I need to approximate them based on the last known value. The ratio of the not-NULLs is between 0.1% and 1%, I have around 100million records, the latest recent hardware, and mssql 2016.

                    – peterh
                    Apr 1 at 2:57





                    Thanks the answer! I have missing data in my input, I need to approximate them based on the last known value. The ratio of the not-NULLs is between 0.1% and 1%, I have around 100million records, the latest recent hardware, and mssql 2016.

                    – peterh
                    Apr 1 at 2:57













                    I used a simple naive queries, without any (indexed) temporary tables, with WITH ... AS constructs. I am happy that ms sql can optimize it if it got enough advices. I am experimenting on.

                    – peterh
                    Apr 1 at 13:04





                    I used a simple naive queries, without any (indexed) temporary tables, with WITH ... AS constructs. I am happy that ms sql can optimize it if it got enough advices. I am experimenting on.

                    – peterh
                    Apr 1 at 13:04













                    @peterh: To restate, in your real data about 99% of the rows have a NULLfor [value]?

                    – Joe Obbish
                    Apr 1 at 22:49





                    @peterh: To restate, in your real data about 99% of the rows have a NULLfor [value]?

                    – Joe Obbish
                    Apr 1 at 22:49













                    Yes. Maybe 99.9. In the real data, also the "value"s are growing with the ids, if it helps.

                    – peterh
                    Apr 2 at 6:11





                    Yes. Maybe 99.9. In the real data, also the "value"s are growing with the ids, if it helps.

                    – peterh
                    Apr 2 at 6:11











                    7














                    One method, by using OVER() and MAX() and COUNT() based on this source could be:



                    SELECT ID, MAX(value) OVER (PARTITION BY Value2) as value
                    FROM
                    (
                    SELECT ID, value
                    ,COUNT(value) OVER (ORDER BY ID) AS Value2
                    FROM dbo.HugeTable
                    ) a
                    ORDER BY ID;


                    Result



                    Id UpdatedValue
                    1 136
                    2 136
                    3 650
                    4 650
                    5 650
                    6 650
                    7 954
                    8 954
                    9 104
                    10 104



                    Another method based on this source, closely related to the first example



                    ;WITH CTE As 
                    (
                    SELECT value,
                    Id,
                    COUNT(value)
                    OVER(ORDER BY Id) As Value2
                    FROM dbo.HugeTable
                    ),

                    CTE2 AS (
                    SELECT Id,
                    value,
                    First_Value(value)
                    OVER( PARTITION BY Value2
                    ORDER BY Id) As UpdatedValue
                    FROM CTE
                    )
                    SELECT Id,UpdatedValue
                    FROM CTE2;





                    share|improve this answer




















                    • 3





                      Consider adding details about how these approaches perform with a "huge table".

                      – Joe Obbish
                      Mar 31 at 22:32











                    • Thanks! This is what I finally did, although not COUNT()... OVER, instead MAX(). It became much faster, but it is still slow. Be back soon.

                      – peterh
                      Apr 1 at 3:02
















                    7














                    One method, by using OVER() and MAX() and COUNT() based on this source could be:



                    SELECT ID, MAX(value) OVER (PARTITION BY Value2) as value
                    FROM
                    (
                    SELECT ID, value
                    ,COUNT(value) OVER (ORDER BY ID) AS Value2
                    FROM dbo.HugeTable
                    ) a
                    ORDER BY ID;


                    Result



                    Id UpdatedValue
                    1 136
                    2 136
                    3 650
                    4 650
                    5 650
                    6 650
                    7 954
                    8 954
                    9 104
                    10 104



                    Another method based on this source, closely related to the first example



                    ;WITH CTE As 
                    (
                    SELECT value,
                    Id,
                    COUNT(value)
                    OVER(ORDER BY Id) As Value2
                    FROM dbo.HugeTable
                    ),

                    CTE2 AS (
                    SELECT Id,
                    value,
                    First_Value(value)
                    OVER( PARTITION BY Value2
                    ORDER BY Id) As UpdatedValue
                    FROM CTE
                    )
                    SELECT Id,UpdatedValue
                    FROM CTE2;





                    share|improve this answer




















                    • 3





                      Consider adding details about how these approaches perform with a "huge table".

                      – Joe Obbish
                      Mar 31 at 22:32











                    • Thanks! This is what I finally did, although not COUNT()... OVER, instead MAX(). It became much faster, but it is still slow. Be back soon.

                      – peterh
                      Apr 1 at 3:02














                    7












                    7








                    7







                    One method, by using OVER() and MAX() and COUNT() based on this source could be:



                    SELECT ID, MAX(value) OVER (PARTITION BY Value2) as value
                    FROM
                    (
                    SELECT ID, value
                    ,COUNT(value) OVER (ORDER BY ID) AS Value2
                    FROM dbo.HugeTable
                    ) a
                    ORDER BY ID;


                    Result



                    Id UpdatedValue
                    1 136
                    2 136
                    3 650
                    4 650
                    5 650
                    6 650
                    7 954
                    8 954
                    9 104
                    10 104



                    Another method based on this source, closely related to the first example



                    ;WITH CTE As 
                    (
                    SELECT value,
                    Id,
                    COUNT(value)
                    OVER(ORDER BY Id) As Value2
                    FROM dbo.HugeTable
                    ),

                    CTE2 AS (
                    SELECT Id,
                    value,
                    First_Value(value)
                    OVER( PARTITION BY Value2
                    ORDER BY Id) As UpdatedValue
                    FROM CTE
                    )
                    SELECT Id,UpdatedValue
                    FROM CTE2;





                    share|improve this answer















                    One method, by using OVER() and MAX() and COUNT() based on this source could be:



                    SELECT ID, MAX(value) OVER (PARTITION BY Value2) as value
                    FROM
                    (
                    SELECT ID, value
                    ,COUNT(value) OVER (ORDER BY ID) AS Value2
                    FROM dbo.HugeTable
                    ) a
                    ORDER BY ID;


                    Result



                    Id UpdatedValue
                    1 136
                    2 136
                    3 650
                    4 650
                    5 650
                    6 650
                    7 954
                    8 954
                    9 104
                    10 104



                    Another method based on this source, closely related to the first example



                    ;WITH CTE As 
                    (
                    SELECT value,
                    Id,
                    COUNT(value)
                    OVER(ORDER BY Id) As Value2
                    FROM dbo.HugeTable
                    ),

                    CTE2 AS (
                    SELECT Id,
                    value,
                    First_Value(value)
                    OVER( PARTITION BY Value2
                    ORDER BY Id) As UpdatedValue
                    FROM CTE
                    )
                    SELECT Id,UpdatedValue
                    FROM CTE2;






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Apr 1 at 13:13

























                    answered Mar 31 at 17:54









                    Randi VertongenRandi Vertongen

                    4,8211924




                    4,8211924







                    • 3





                      Consider adding details about how these approaches perform with a "huge table".

                      – Joe Obbish
                      Mar 31 at 22:32











                    • Thanks! This is what I finally did, although not COUNT()... OVER, instead MAX(). It became much faster, but it is still slow. Be back soon.

                      – peterh
                      Apr 1 at 3:02













                    • 3





                      Consider adding details about how these approaches perform with a "huge table".

                      – Joe Obbish
                      Mar 31 at 22:32











                    • Thanks! This is what I finally did, although not COUNT()... OVER, instead MAX(). It became much faster, but it is still slow. Be back soon.

                      – peterh
                      Apr 1 at 3:02








                    3




                    3





                    Consider adding details about how these approaches perform with a "huge table".

                    – Joe Obbish
                    Mar 31 at 22:32





                    Consider adding details about how these approaches perform with a "huge table".

                    – Joe Obbish
                    Mar 31 at 22:32













                    Thanks! This is what I finally did, although not COUNT()... OVER, instead MAX(). It became much faster, but it is still slow. Be back soon.

                    – peterh
                    Apr 1 at 3:02






                    Thanks! This is what I finally did, although not COUNT()... OVER, instead MAX(). It became much faster, but it is still slow. Be back soon.

                    – peterh
                    Apr 1 at 3:02


















                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Database Administrators Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f233610%2fhow-to-get-the-last-not-null-value-in-an-ordered-column-of-a-huge-table%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Boston (Lincolnshire) Stedsbyld | Berne yn Boston | NavigaasjemenuBoston Borough CouncilBoston, Lincolnshire

                    Ballerup Komuun Stääden an saarpen | Futnuuten | Luke uk diar | Nawigatsjuunwww.ballerup.dkwww.statistikbanken.dk: Tabelle BEF44 (Folketal pr. 1. januar fordelt på byer)Commonskategorii: Ballerup Komuun55° 44′ N, 12° 22′ O

                    Serbia Índice Etimología Historia Geografía Entorno natural División administrativa Política Demografía Economía Cultura Deportes Véase también Notas Referencias Bibliografía Enlaces externos Menú de navegación44°49′00″N 20°28′00″E / 44.816666666667, 20.46666666666744°49′00″N 20°28′00″E / 44.816666666667, 20.466666666667U.S. Department of Commerce (2015)«Informe sobre Desarrollo Humano 2018»Kosovo-Metohija.Neutralna Srbija u NATO okruzenju.The SerbsTheories on the Origin of the Serbs.Serbia.Earls: Webster's Quotations, Facts and Phrases.Egeo y Balcanes.Kalemegdan.Southern Pannonia during the age of the Great Migrations.Culture in Serbia.History.The Serbian Origin of the Montenegrins.Nemanjics' period (1186-1353).Stefan Uros (1355-1371).Serbian medieval history.Habsburg–Ottoman Wars (1525–1718).The Ottoman Empire, 1700-1922.The First Serbian Uprising.Miloš, prince of Serbia.3. Bosnia-Hercegovina and the Congress of Berlin.The Balkan Wars and the Partition of Macedonia.The Falcon and the Eagle: Montenegro and Austria-Hungary, 1908-1914.Typhus fever on the eastern front in World War I.Anniversary of WWI battle marked in Serbia.La derrota austriaca en los Balcanes. Fin del Imperio Austro-Húngaro.Imperio austriaco y Reino de Hungría.Los tiempos modernos: del capitalismo a la globalización, siglos XVII al XXI.The period of Croatia within ex-Yugoslavia.Yugoslavia: Much in a Name.Las dictaduras europeas.Croacia: mito y realidad."Crods ask arms".Prólogo a la invasión.La campaña de los Balcanes.La resistencia en Yugoslavia.Jasenovac Research Institute.Día en memoria de las víctimas del genocidio en la Segunda Guerra Mundial.El infierno estuvo en Jasenovac.Croacia empieza a «desenterrar» a sus muertos de Jasenovac.World fascism: a historical encyclopedia, Volumen 1.Tito. Josip Broz.El nuevo orden y la resistencia.La conquista del poder.Algunos aspectos de la economía yugoslava a mediados de 1962.Albania-Kosovo crisis.De Kosovo a Kosova: una visión demográfica.La crisis de la economía yugoslava y la política de "estabilización".Milosevic: el poder de un absolutista."Serbia under Milošević: politics in the 1990s"Milosevic cavó en Kosovo la tumba de la antigua Yugoslavia.La ONU exculpa a Serbia de genocidio en la guerra de Bosnia.Slobodan Milosevic, el burócrata que supo usar el odio.Es la fuerza contra el sufrimiento de muchos inocentes.Matanza de civiles al bombardear la OTAN un puente mientras pasaba un tren.Las consecuencias negativas de los bombardeos de Yugoslavia se sentirán aún durante largo tiempo.Kostunica advierte que la misión de Europa en Kosovo es ilegal.Las 24 horas más largas en la vida de Slobodan Milosevic.Serbia declara la guerra a la mafia por matar a Djindjic.Tadic presentará "quizás en diciembre" la solicitud de entrada en la UE.Montenegro declara su independencia de Serbia.Serbia se declara estado soberano tras separación de Montenegro.«Accordance with International Law of the Unilateral Declaration of Independence by the Provisional Institutions of Self-Government of Kosovo (Request for Advisory Opinion)»Mladic pasa por el médico antes de la audiencia para extraditarloDatos de Serbia y Kosovo.The Carpathian Mountains.Position, Relief, Climate.Transport.Finding birds in Serbia.U Srbiji do 2010. godine 10% teritorije nacionalni parkovi.Geography.Serbia: Climate.Variability of Climate In Serbia In The Second Half of The 20thc Entury.BASIC CLIMATE CHARACTERISTICS FOR THE TERRITORY OF SERBIA.Fauna y flora: Serbia.Serbia and Montenegro.Información general sobre Serbia.Republic of Serbia Environmental Protection Agency (SEPA).Serbia recycling 15% of waste.Reform process of the Serbian energy sector.20-MW Wind Project Being Developed in Serbia.Las Naciones Unidas. Paz para Kosovo.Aniversario sin fiesta.Population by national or ethnic groups by Census 2002.Article 7. Coat of arms, flag and national anthem.Serbia, flag of.Historia.«Serbia and Montenegro in Pictures»Serbia.Serbia aprueba su nueva Constitución con un apoyo de más del 50%.Serbia. Population.«El nacionalista Nikolic gana las elecciones presidenciales en Serbia»El europeísta Borís Tadic gana la segunda vuelta de las presidenciales serbias.Aleksandar Vucic, de ultranacionalista serbio a fervoroso europeístaKostunica condena la declaración del "falso estado" de Kosovo.Comienza el debate sobre la independencia de Kosovo en el TIJ.La Corte Internacional de Justicia dice que Kosovo no violó el derecho internacional al declarar su independenciaKosovo: Enviado de la ONU advierte tensiones y fragilidad.«Bruselas recomienda negociar la adhesión de Serbia tras el acuerdo sobre Kosovo»Monografía de Serbia.Bez smanjivanja Vojske Srbije.Military statistics Serbia and Montenegro.Šutanovac: Vojni budžet za 2009. godinu 70 milijardi dinara.Serbia-Montenegro shortens obligatory military service to six months.No hay justicia para las víctimas de los bombardeos de la OTAN.Zapatero reitera la negativa de España a reconocer la independencia de Kosovo.Anniversary of the signing of the Stabilisation and Association Agreement.Detenido en Serbia Radovan Karadzic, el criminal de guerra más buscado de Europa."Serbia presentará su candidatura de acceso a la UE antes de fin de año".Serbia solicita la adhesión a la UE.Detenido el exgeneral serbobosnio Ratko Mladic, principal acusado del genocidio en los Balcanes«Lista de todos los Estados Miembros de las Naciones Unidas que son parte o signatarios en los diversos instrumentos de derechos humanos de las Naciones Unidas»versión pdfProtocolo Facultativo de la Convención sobre la Eliminación de todas las Formas de Discriminación contra la MujerConvención contra la tortura y otros tratos o penas crueles, inhumanos o degradantesversión pdfProtocolo Facultativo de la Convención sobre los Derechos de las Personas con DiscapacidadEl ACNUR recibe con beneplácito el envío de tropas de la OTAN a Kosovo y se prepara ante una posible llegada de refugiados a Serbia.Kosovo.- El jefe de la Minuk denuncia que los serbios boicotearon las legislativas por 'presiones'.Bosnia and Herzegovina. Population.Datos básicos de Montenegro, historia y evolución política.Serbia y Montenegro. Indicador: Tasa global de fecundidad (por 1000 habitantes).Serbia y Montenegro. Indicador: Tasa bruta de mortalidad (por 1000 habitantes).Population.Falleció el patriarca de la Iglesia Ortodoxa serbia.Atacan en Kosovo autobuses con peregrinos tras la investidura del patriarca serbio IrinejSerbian in Hungary.Tasas de cambio."Kosovo es de todos sus ciudadanos".Report for Serbia.Country groups by income.GROSS DOMESTIC PRODUCT (GDP) OF THE REPUBLIC OF SERBIA 1997–2007.Economic Trends in the Republic of Serbia 2006.National Accounts Statitics.Саопштења за јавност.GDP per inhabitant varied by one to six across the EU27 Member States.Un pacto de estabilidad para Serbia.Unemployment rate rises in Serbia.Serbia, Belarus agree free trade to woo investors.Serbia, Turkey call investors to Serbia.Success Stories.U.S. Private Investment in Serbia and Montenegro.Positive trend.Banks in Serbia.La Cámara de Comercio acompaña a empresas madrileñas a Serbia y Croacia.Serbia Industries.Energy and mining.Agriculture.Late crops, fruit and grapes output, 2008.Rebranding Serbia: A Hobby Shortly to Become a Full-Time Job.Final data on livestock statistics, 2008.Serbian cell-phone users.U Srbiji sve više računara.Телекомуникације.U Srbiji 27 odsto gradjana koristi Internet.Serbia and Montenegro.Тренд гледаности програма РТС-а у 2008. и 2009.години.Serbian railways.General Terms.El mercado del transporte aéreo en Serbia.Statistics.Vehículos de motor registrados.Planes ambiciosos para el transporte fluvial.Turismo.Turistički promet u Republici Srbiji u periodu januar-novembar 2007. godine.Your Guide to Culture.Novi Sad - city of culture.Nis - european crossroads.Serbia. Properties inscribed on the World Heritage List .Stari Ras and Sopoćani.Studenica Monastery.Medieval Monuments in Kosovo.Gamzigrad-Romuliana, Palace of Galerius.Skiing and snowboarding in Kopaonik.Tara.New7Wonders of Nature Finalists.Pilgrimage of Saint Sava.Exit Festival: Best european festival.Banje u Srbiji.«The Encyclopedia of world history»Culture.Centenario del arte serbio.«Djordje Andrejevic Kun: el único pintor de los brigadistas yugoslavos de la guerra civil española»About the museum.The collections.Miroslav Gospel – Manuscript from 1180.Historicity in the Serbo-Croatian Heroic Epic.Culture and Sport.Conversación con el rector del Seminario San Sava.'Reina Margot' funde drama, historia y gesto con música de Goran Bregovic.Serbia gana Eurovisión y España decepciona de nuevo con un vigésimo puesto.Home.Story.Emir Kusturica.Tercer oro para Paskaljevic.Nikola Tesla Year.Home.Tesla, un genio tomado por loco.Aniversario de la muerte de Nikola Tesla.El Museo Nikola Tesla en Belgrado.El inventor del mundo actual.República de Serbia.University of Belgrade official statistics.University of Novi Sad.University of Kragujevac.University of Nis.Comida. Cocina serbia.Cooking.Montenegro se convertirá en el miembro 204 del movimiento olímpico.España, campeona de Europa de baloncesto.El Partizan de Belgrado se corona campeón por octava vez consecutiva.Serbia se clasifica para el Mundial de 2010 de Sudáfrica.Serbia Name Squad For Northern Ireland And South Korea Tests.Fútbol.- El Partizán de Belgrado se proclama campeón de la Liga serbia.Clasificacion final Mundial de balonmano Croacia 2009.Serbia vence a España y se consagra campeón mundial de waterpolo.Novak Djokovic no convence pero gana en Australia.Gana Ana Ivanovic el Roland Garros.Serena Williams gana el US Open por tercera vez.Biography.Bradt Travel Guide SerbiaThe Encyclopedia of World War IGobierno de SerbiaPortal del Gobierno de SerbiaPresidencia de SerbiaAsamblea Nacional SerbiaMinisterio de Asuntos exteriores de SerbiaBanco Nacional de SerbiaAgencia Serbia para la Promoción de la Inversión y la ExportaciónOficina de Estadísticas de SerbiaCIA. Factbook 2008Organización nacional de turismo de SerbiaDiscover SerbiaConoce SerbiaNoticias de SerbiaSerbiaWorldCat1512028760000 0000 9526 67094054598-2n8519591900570825ge1309191004530741010url17413117006669D055771Serbia