SQL Server query scanning more partitions than expectedPartition Key questions in SQL Server 2008db2 range partitioning attach and detach issueWhy won't Oracle alter the size of a column that is used for sub partitioning?SQL Partioning on date, how does it work for future records?effective mysql table/index design for 35 million rows+ table, with 200+ corresponding columns (double), any combination of which may be queriedWhy can an Oracle SET UNUSED COLUMN cause internal UPDATE SET X=X and huge log generation?Getting a realistic query plan when partitioning with low volumes of dataHow to maintain a global index on a large table undergoing regular partition purges?SQL Error: ORA-14300: While partitioning and subpartitioningSQL Server 2014 Transactional Replication Partition SwitchingMerge replication - corrupt row continually trying to INSERT

Defending Castle from Zombies

What is the purpose of Strength, Intelligence and Dexterity in Path of Exile?

Cutting numbers into a specific decimals

In Endgame, wouldn't Stark have remembered Hulk busting out of the stairwell?

Why haven't the British protested Brexit as ardently like Hong Kongers protest?

Is it unusual for a math department not to have a mail/web server?

Is there a way to tell what frequency I need a PWM to be?

Line Feed in monospace font - Macro

Can a network vulnerability be exploited locally?

Does throwing a non-weapon item take an action?

Generic Extension Method To Count Descendants

The meaning of asynchronous vs synchronous

Alternative to Magnesium's Role in Photosynthesis

What is Soda Fountain Etiquette?

Where should I draw the line on follow up questions from previous employer

Are there any to-scale diagrams of the TRAPPIST-1 system?

What is the following VRP?

What does it mean to move a single flight control to its full deflection?

Group riding etiquette

Is this password scheme legit?

Pen test results for web application include a file from a forbidden directory that is not even used or referenced

Do application leftovers have any impact on performance?

How does attacking during a conversation affect initiative?

Principal payments



SQL Server query scanning more partitions than expected


Partition Key questions in SQL Server 2008db2 range partitioning attach and detach issueWhy won't Oracle alter the size of a column that is used for sub partitioning?SQL Partioning on date, how does it work for future records?effective mysql table/index design for 35 million rows+ table, with 200+ corresponding columns (double), any combination of which may be queriedWhy can an Oracle SET UNUSED COLUMN cause internal UPDATE SET X=X and huge log generation?Getting a realistic query plan when partitioning with low volumes of dataHow to maintain a global index on a large table undergoing regular partition purges?SQL Error: ORA-14300: While partitioning and subpartitioningSQL Server 2014 Transactional Replication Partition SwitchingMerge replication - corrupt row continually trying to INSERT






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








4















So my team has the following select statement in one of our stored procedures



SELECT
ai.Name
,dc.Component
,SUM(dc.Value) Value
FROM
Warm.DailyCosts dc
JOIN Warm.AccountInfo ai
ON dc.AccountInfoId = ai.Id
WHERE
ai.CorrelationId = '00000000-0000-0000-0000-000000000000'
AND ((dc.CalendarId >= (20190601 + ai.DayOfMonth - 1)
AND dc.CalendarId < 20190701)
OR (dc.CalendarId >= 20270601
AND dc.CalendarId < (20270601 + ai.DayOfMonth - 1)))
GROUP BY
Name
,Component


And we've partitioned the DailyCosts table on the months of each year as follows:



CREATE PARTITION FUNCTION [PF_CostDateByYearMonth](int) AS RANGE RIGHT FOR VALUES (
20180101,
20180201,
20180301,
20180401,
20180501,
20180601,
20180701,
20180801,
20180901,
20181001,
20181101,
20181201,

...

20300101,
20300201,
20300301,
20300401,
20300501,
20300601,
20300701,
20300801,
20300901,
20301001,
20301101,
20301201)


We noticed that when we ran the procedure, rather than finding the appropriate partitions right away it looked like it was scanning partitions from either end. For the above example, it viewed partitions 20180101 up to 20190701 and 20301201 down to 20270601 totaling 62 partitions.



When we removed the math from the where statement (+ ai.DayOfMonth - 1), the partitions read dropped down to 2, 20190601 and 20270601, as expected. Note that we use seed data and DayOfMonth is set to 15 on every account.



What causes the server to scan the partitions when this math is included, and is it actually looking through all of the indexes in these partitions or is it just checking their ranges and moving on?



Any and all sources you can provide would go a long way in helping us understand!










share|improve this question






























    4















    So my team has the following select statement in one of our stored procedures



    SELECT
    ai.Name
    ,dc.Component
    ,SUM(dc.Value) Value
    FROM
    Warm.DailyCosts dc
    JOIN Warm.AccountInfo ai
    ON dc.AccountInfoId = ai.Id
    WHERE
    ai.CorrelationId = '00000000-0000-0000-0000-000000000000'
    AND ((dc.CalendarId >= (20190601 + ai.DayOfMonth - 1)
    AND dc.CalendarId < 20190701)
    OR (dc.CalendarId >= 20270601
    AND dc.CalendarId < (20270601 + ai.DayOfMonth - 1)))
    GROUP BY
    Name
    ,Component


    And we've partitioned the DailyCosts table on the months of each year as follows:



    CREATE PARTITION FUNCTION [PF_CostDateByYearMonth](int) AS RANGE RIGHT FOR VALUES (
    20180101,
    20180201,
    20180301,
    20180401,
    20180501,
    20180601,
    20180701,
    20180801,
    20180901,
    20181001,
    20181101,
    20181201,

    ...

    20300101,
    20300201,
    20300301,
    20300401,
    20300501,
    20300601,
    20300701,
    20300801,
    20300901,
    20301001,
    20301101,
    20301201)


    We noticed that when we ran the procedure, rather than finding the appropriate partitions right away it looked like it was scanning partitions from either end. For the above example, it viewed partitions 20180101 up to 20190701 and 20301201 down to 20270601 totaling 62 partitions.



    When we removed the math from the where statement (+ ai.DayOfMonth - 1), the partitions read dropped down to 2, 20190601 and 20270601, as expected. Note that we use seed data and DayOfMonth is set to 15 on every account.



    What causes the server to scan the partitions when this math is included, and is it actually looking through all of the indexes in these partitions or is it just checking their ranges and moving on?



    Any and all sources you can provide would go a long way in helping us understand!










    share|improve this question


























      4












      4








      4


      1






      So my team has the following select statement in one of our stored procedures



      SELECT
      ai.Name
      ,dc.Component
      ,SUM(dc.Value) Value
      FROM
      Warm.DailyCosts dc
      JOIN Warm.AccountInfo ai
      ON dc.AccountInfoId = ai.Id
      WHERE
      ai.CorrelationId = '00000000-0000-0000-0000-000000000000'
      AND ((dc.CalendarId >= (20190601 + ai.DayOfMonth - 1)
      AND dc.CalendarId < 20190701)
      OR (dc.CalendarId >= 20270601
      AND dc.CalendarId < (20270601 + ai.DayOfMonth - 1)))
      GROUP BY
      Name
      ,Component


      And we've partitioned the DailyCosts table on the months of each year as follows:



      CREATE PARTITION FUNCTION [PF_CostDateByYearMonth](int) AS RANGE RIGHT FOR VALUES (
      20180101,
      20180201,
      20180301,
      20180401,
      20180501,
      20180601,
      20180701,
      20180801,
      20180901,
      20181001,
      20181101,
      20181201,

      ...

      20300101,
      20300201,
      20300301,
      20300401,
      20300501,
      20300601,
      20300701,
      20300801,
      20300901,
      20301001,
      20301101,
      20301201)


      We noticed that when we ran the procedure, rather than finding the appropriate partitions right away it looked like it was scanning partitions from either end. For the above example, it viewed partitions 20180101 up to 20190701 and 20301201 down to 20270601 totaling 62 partitions.



      When we removed the math from the where statement (+ ai.DayOfMonth - 1), the partitions read dropped down to 2, 20190601 and 20270601, as expected. Note that we use seed data and DayOfMonth is set to 15 on every account.



      What causes the server to scan the partitions when this math is included, and is it actually looking through all of the indexes in these partitions or is it just checking their ranges and moving on?



      Any and all sources you can provide would go a long way in helping us understand!










      share|improve this question














      So my team has the following select statement in one of our stored procedures



      SELECT
      ai.Name
      ,dc.Component
      ,SUM(dc.Value) Value
      FROM
      Warm.DailyCosts dc
      JOIN Warm.AccountInfo ai
      ON dc.AccountInfoId = ai.Id
      WHERE
      ai.CorrelationId = '00000000-0000-0000-0000-000000000000'
      AND ((dc.CalendarId >= (20190601 + ai.DayOfMonth - 1)
      AND dc.CalendarId < 20190701)
      OR (dc.CalendarId >= 20270601
      AND dc.CalendarId < (20270601 + ai.DayOfMonth - 1)))
      GROUP BY
      Name
      ,Component


      And we've partitioned the DailyCosts table on the months of each year as follows:



      CREATE PARTITION FUNCTION [PF_CostDateByYearMonth](int) AS RANGE RIGHT FOR VALUES (
      20180101,
      20180201,
      20180301,
      20180401,
      20180501,
      20180601,
      20180701,
      20180801,
      20180901,
      20181001,
      20181101,
      20181201,

      ...

      20300101,
      20300201,
      20300301,
      20300401,
      20300501,
      20300601,
      20300701,
      20300801,
      20300901,
      20301001,
      20301101,
      20301201)


      We noticed that when we ran the procedure, rather than finding the appropriate partitions right away it looked like it was scanning partitions from either end. For the above example, it viewed partitions 20180101 up to 20190701 and 20301201 down to 20270601 totaling 62 partitions.



      When we removed the math from the where statement (+ ai.DayOfMonth - 1), the partitions read dropped down to 2, 20190601 and 20270601, as expected. Note that we use seed data and DayOfMonth is set to 15 on every account.



      What causes the server to scan the partitions when this math is included, and is it actually looking through all of the indexes in these partitions or is it just checking their ranges and moving on?



      Any and all sources you can provide would go a long way in helping us understand!







      sql-server partitioning






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Aug 16 at 21:42









      BenBen

      233 bronze badges




      233 bronze badges























          1 Answer
          1






          active

          oldest

          votes


















          9















          Reasoning



          When comparing the column of the non partitioned table against the partitioned table, sql server will not be able to know what DayOfMonth will hold, even if all of them are 15.



          As a result it would not know which partitions to return to satisfy this filtering when joining the two tables.



          A different example to give some more insight can be found here.




          Testing



          I was able to recreate your issue, for further questions please add as much information as possible.
          This could be Table definition, indexes, partition scheme, ...



          The DDL & DML is at the bottom.



          When running the query we can get the same result:



          enter image description here



          62 partitions returned.



          On the seek predicates it tries to filter what it can, this is the two filters on CalendarId that do not have the + DayOfMonth-1.



          enter image description here



          This translates to



          WHERE ...
          AND (( dc.CalendarId < 20190701)
          OR (dc.CalendarId >= 20270601))
          ...


          When running the query with these filters you will see the same amount of rows returned on accessing the table in the query plan.



          Only after getting this data, it can and will be joined to the AccountInfo table on the ID's and the DayOfMonth - 1



          enter image description here



          enter image description here



          To confirm your statement that when we remove the column that only two partitions are scanned:



          SELECT
          ai.Name
          ,SUM(dc.Component )
          ,SUM(dc.Value) Value
          FROM
          Warm.DailyCosts dc
          JOIN Warm.AccountInfo ai
          ON dc.AccountInfoId = ai.Id
          WHERE
          ai.CorrelationId = '00000000-0000-0000-0000-000000000000'
          AND ((dc.CalendarId >= (20190601 - 1)
          AND dc.CalendarId < 20190701)
          OR (dc.CalendarId >= 20270601
          AND dc.CalendarId < (20270601 - 1)))
          GROUP BY Name


          Only two are accessed and used:



          a




          Solution



          I am going to assume that DayOfMonth only goes up to 31 days.



          If you know these boundaries, you can 'hard code' them so that sql server knows what partitions to look for. After this you can add the extra filtering.



          E.G.



          WITH CTE
          AS
          (
          SELECT
          ai.Name
          ,dc.Component
          ,dc.Value
          ,dc.CalendarId
          ,ai.DayOfMonth
          FROM
          Warm.DailyCosts dc
          JOIN Warm.AccountInfo ai
          ON dc.AccountInfoId = ai.Id
          WHERE
          ai.CorrelationId = '00000000-0000-0000-0000-000000000000'
          AND ((dc.CalendarId >= (20190601 )
          AND dc.CalendarId < 20190701)
          OR (dc.CalendarId >= 20270601
          AND dc.CalendarId < (20270701)))

          )

          SELECT Name,Component,SUM(Value)
          FROM CTE
          WHERE ((CalendarId >= (20190601 + DayOfMonth - 1)
          AND CalendarId < 20190701)
          OR (CalendarId >= 20270601
          AND CalendarId < (20270601 + DayOfMonth - 1)))

          GROUP BY
          Name
          ,Component


          The sole purpose of the cte is to let sql server know that it can also filter on dc.CalendarId >= dc.CalendarId >= (20190601 ) OR dc.CalendarId < (20270701)).



          Sidenote: Adding a constraint does not work to enforce this.



          This query gives us the result we want, with the correct partition elemination:



          enter image description here



          enter image description here



          Only accessing partitions 19 & 21.



          You can probably also use OR / AND logic to get the same result if you prefer. The important part is getting the boundaries known.




          Test data



          CREATE SCHEMA WARM
          GO

          CREATE TABLE Warm.DailyCosts(ID INT IDENTITY(1,1) NOT NULL,
          Component int,
          Value int,
          CalendarId INT,
          AccountInfoId int
          )


          CREATE TABLE Warm.AccountInfo(Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
          Name VARCHAR(25),
          CorrelationId uniqueidentifier,
          DayOfMonth int
          );
          USE [master]
          GO
          ALTER DATABASE [test] ADD FILEGROUP [Partitionfg]
          GO
          USE [test]
          GO
          CREATE PARTITION FUNCTION [PF_CostDateByYearMonth](int) AS RANGE RIGHT FOR VALUES (
          20180101,
          20180201,
          20180301,
          20180401,
          20180501,
          20180601,
          20180701,
          20180801,
          20180901,
          20181001,
          20181101,
          20181201,
          20190101,
          20190201,
          20190301,
          20190401,
          20190501,
          20190601,
          20190701,
          20270601,
          20270701,
          20270801,
          20270901,
          20271001,
          20271101,
          20271201,
          20280101,
          20280201,
          20280301,
          20280401,
          20280501,
          20280601,
          20280701,
          20280801,
          20280901,
          20281001,
          20281101,
          20281201,
          20290101,
          20290201,
          20290301,
          20290401,
          20290501,
          20290601,
          20290701,
          20290801,
          20290901,
          20291001,
          20291101,
          20291201,
          20300101,
          20300201,
          20300301,
          20300401,
          20300501,
          20300601,
          20300701,
          20300801,
          20300901,
          20301001,
          20301101,
          20301201)


          CREATE PARTITION SCHEME [PS_CostDateByYearMonth]
          AS PARTITION [PF_CostDateByYearMonth]
          ALL TO ( [Partitionfg] );

          CREATE UNIQUE CLUSTERED INDEX ptci ON Warm.DailyCosts(CalendarId,Id) ON [PS_CostDateByYearMonth](CalendarId) ;
          USE [master]
          GO
          ALTER DATABASE [test] ADD FILE ( NAME = N'TestPartition', FILENAME = N'D:DATATestPartition.ndf' , SIZE = 3072KB , FILEGROWTH = 65536KB ) TO FILEGROUP [Partitionfg]
          GO
          USE [test]
          GO

          INSERT INTO Warm.DailyCosts(Component,
          Value,
          CalendarId,
          AccountInfoId
          )
          SELECT TOP(1000000) --1M
          ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
          ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
          20180101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
          ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
          FROM master..spt_values spt1
          CROSS APPLY master..spt_values spt2
          -- 2018
          INSERT INTO Warm.DailyCosts(Component,
          Value,
          CalendarId,
          AccountInfoId
          )
          SELECT TOP(1000000) --1M
          ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
          ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
          20190101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
          ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
          FROM master..spt_values spt1
          CROSS APPLY master..spt_values spt2
          -- 2019
          INSERT INTO Warm.DailyCosts(Component,
          Value,
          CalendarId,
          AccountInfoId
          )

          SELECT TOP(1000000) --1M
          ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
          ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
          20280101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
          ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
          FROM master..spt_values spt1
          CROSS APPLY master..spt_values spt2
          -- 2028

          INSERT INTO Warm.AccountInfo(
          Name ,
          CorrelationId,
          DayOfMonth
          )

          SELECT TOP(3000000) --3M
          CAST(ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS varchar(10)) + 'a',
          '00000000-0000-0000-0000-000000000000',
          15
          FROM master..spt_values spt1
          CROSS APPLY master..spt_values spt2
          CREATE NONCLUSTERED INDEX [IX_Component_Value_DailyCosts] ON Warm.DailyCosts
          (Component,Value)
          ON [PS_CostDateByYearMonth](CalendarId);
          GO





          share|improve this answer





























            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%2f245575%2fsql-server-query-scanning-more-partitions-than-expected%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            9















            Reasoning



            When comparing the column of the non partitioned table against the partitioned table, sql server will not be able to know what DayOfMonth will hold, even if all of them are 15.



            As a result it would not know which partitions to return to satisfy this filtering when joining the two tables.



            A different example to give some more insight can be found here.




            Testing



            I was able to recreate your issue, for further questions please add as much information as possible.
            This could be Table definition, indexes, partition scheme, ...



            The DDL & DML is at the bottom.



            When running the query we can get the same result:



            enter image description here



            62 partitions returned.



            On the seek predicates it tries to filter what it can, this is the two filters on CalendarId that do not have the + DayOfMonth-1.



            enter image description here



            This translates to



            WHERE ...
            AND (( dc.CalendarId < 20190701)
            OR (dc.CalendarId >= 20270601))
            ...


            When running the query with these filters you will see the same amount of rows returned on accessing the table in the query plan.



            Only after getting this data, it can and will be joined to the AccountInfo table on the ID's and the DayOfMonth - 1



            enter image description here



            enter image description here



            To confirm your statement that when we remove the column that only two partitions are scanned:



            SELECT
            ai.Name
            ,SUM(dc.Component )
            ,SUM(dc.Value) Value
            FROM
            Warm.DailyCosts dc
            JOIN Warm.AccountInfo ai
            ON dc.AccountInfoId = ai.Id
            WHERE
            ai.CorrelationId = '00000000-0000-0000-0000-000000000000'
            AND ((dc.CalendarId >= (20190601 - 1)
            AND dc.CalendarId < 20190701)
            OR (dc.CalendarId >= 20270601
            AND dc.CalendarId < (20270601 - 1)))
            GROUP BY Name


            Only two are accessed and used:



            a




            Solution



            I am going to assume that DayOfMonth only goes up to 31 days.



            If you know these boundaries, you can 'hard code' them so that sql server knows what partitions to look for. After this you can add the extra filtering.



            E.G.



            WITH CTE
            AS
            (
            SELECT
            ai.Name
            ,dc.Component
            ,dc.Value
            ,dc.CalendarId
            ,ai.DayOfMonth
            FROM
            Warm.DailyCosts dc
            JOIN Warm.AccountInfo ai
            ON dc.AccountInfoId = ai.Id
            WHERE
            ai.CorrelationId = '00000000-0000-0000-0000-000000000000'
            AND ((dc.CalendarId >= (20190601 )
            AND dc.CalendarId < 20190701)
            OR (dc.CalendarId >= 20270601
            AND dc.CalendarId < (20270701)))

            )

            SELECT Name,Component,SUM(Value)
            FROM CTE
            WHERE ((CalendarId >= (20190601 + DayOfMonth - 1)
            AND CalendarId < 20190701)
            OR (CalendarId >= 20270601
            AND CalendarId < (20270601 + DayOfMonth - 1)))

            GROUP BY
            Name
            ,Component


            The sole purpose of the cte is to let sql server know that it can also filter on dc.CalendarId >= dc.CalendarId >= (20190601 ) OR dc.CalendarId < (20270701)).



            Sidenote: Adding a constraint does not work to enforce this.



            This query gives us the result we want, with the correct partition elemination:



            enter image description here



            enter image description here



            Only accessing partitions 19 & 21.



            You can probably also use OR / AND logic to get the same result if you prefer. The important part is getting the boundaries known.




            Test data



            CREATE SCHEMA WARM
            GO

            CREATE TABLE Warm.DailyCosts(ID INT IDENTITY(1,1) NOT NULL,
            Component int,
            Value int,
            CalendarId INT,
            AccountInfoId int
            )


            CREATE TABLE Warm.AccountInfo(Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
            Name VARCHAR(25),
            CorrelationId uniqueidentifier,
            DayOfMonth int
            );
            USE [master]
            GO
            ALTER DATABASE [test] ADD FILEGROUP [Partitionfg]
            GO
            USE [test]
            GO
            CREATE PARTITION FUNCTION [PF_CostDateByYearMonth](int) AS RANGE RIGHT FOR VALUES (
            20180101,
            20180201,
            20180301,
            20180401,
            20180501,
            20180601,
            20180701,
            20180801,
            20180901,
            20181001,
            20181101,
            20181201,
            20190101,
            20190201,
            20190301,
            20190401,
            20190501,
            20190601,
            20190701,
            20270601,
            20270701,
            20270801,
            20270901,
            20271001,
            20271101,
            20271201,
            20280101,
            20280201,
            20280301,
            20280401,
            20280501,
            20280601,
            20280701,
            20280801,
            20280901,
            20281001,
            20281101,
            20281201,
            20290101,
            20290201,
            20290301,
            20290401,
            20290501,
            20290601,
            20290701,
            20290801,
            20290901,
            20291001,
            20291101,
            20291201,
            20300101,
            20300201,
            20300301,
            20300401,
            20300501,
            20300601,
            20300701,
            20300801,
            20300901,
            20301001,
            20301101,
            20301201)


            CREATE PARTITION SCHEME [PS_CostDateByYearMonth]
            AS PARTITION [PF_CostDateByYearMonth]
            ALL TO ( [Partitionfg] );

            CREATE UNIQUE CLUSTERED INDEX ptci ON Warm.DailyCosts(CalendarId,Id) ON [PS_CostDateByYearMonth](CalendarId) ;
            USE [master]
            GO
            ALTER DATABASE [test] ADD FILE ( NAME = N'TestPartition', FILENAME = N'D:DATATestPartition.ndf' , SIZE = 3072KB , FILEGROWTH = 65536KB ) TO FILEGROUP [Partitionfg]
            GO
            USE [test]
            GO

            INSERT INTO Warm.DailyCosts(Component,
            Value,
            CalendarId,
            AccountInfoId
            )
            SELECT TOP(1000000) --1M
            ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
            ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
            20180101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
            ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
            FROM master..spt_values spt1
            CROSS APPLY master..spt_values spt2
            -- 2018
            INSERT INTO Warm.DailyCosts(Component,
            Value,
            CalendarId,
            AccountInfoId
            )
            SELECT TOP(1000000) --1M
            ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
            ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
            20190101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
            ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
            FROM master..spt_values spt1
            CROSS APPLY master..spt_values spt2
            -- 2019
            INSERT INTO Warm.DailyCosts(Component,
            Value,
            CalendarId,
            AccountInfoId
            )

            SELECT TOP(1000000) --1M
            ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
            ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
            20280101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
            ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
            FROM master..spt_values spt1
            CROSS APPLY master..spt_values spt2
            -- 2028

            INSERT INTO Warm.AccountInfo(
            Name ,
            CorrelationId,
            DayOfMonth
            )

            SELECT TOP(3000000) --3M
            CAST(ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS varchar(10)) + 'a',
            '00000000-0000-0000-0000-000000000000',
            15
            FROM master..spt_values spt1
            CROSS APPLY master..spt_values spt2
            CREATE NONCLUSTERED INDEX [IX_Component_Value_DailyCosts] ON Warm.DailyCosts
            (Component,Value)
            ON [PS_CostDateByYearMonth](CalendarId);
            GO





            share|improve this answer































              9















              Reasoning



              When comparing the column of the non partitioned table against the partitioned table, sql server will not be able to know what DayOfMonth will hold, even if all of them are 15.



              As a result it would not know which partitions to return to satisfy this filtering when joining the two tables.



              A different example to give some more insight can be found here.




              Testing



              I was able to recreate your issue, for further questions please add as much information as possible.
              This could be Table definition, indexes, partition scheme, ...



              The DDL & DML is at the bottom.



              When running the query we can get the same result:



              enter image description here



              62 partitions returned.



              On the seek predicates it tries to filter what it can, this is the two filters on CalendarId that do not have the + DayOfMonth-1.



              enter image description here



              This translates to



              WHERE ...
              AND (( dc.CalendarId < 20190701)
              OR (dc.CalendarId >= 20270601))
              ...


              When running the query with these filters you will see the same amount of rows returned on accessing the table in the query plan.



              Only after getting this data, it can and will be joined to the AccountInfo table on the ID's and the DayOfMonth - 1



              enter image description here



              enter image description here



              To confirm your statement that when we remove the column that only two partitions are scanned:



              SELECT
              ai.Name
              ,SUM(dc.Component )
              ,SUM(dc.Value) Value
              FROM
              Warm.DailyCosts dc
              JOIN Warm.AccountInfo ai
              ON dc.AccountInfoId = ai.Id
              WHERE
              ai.CorrelationId = '00000000-0000-0000-0000-000000000000'
              AND ((dc.CalendarId >= (20190601 - 1)
              AND dc.CalendarId < 20190701)
              OR (dc.CalendarId >= 20270601
              AND dc.CalendarId < (20270601 - 1)))
              GROUP BY Name


              Only two are accessed and used:



              a




              Solution



              I am going to assume that DayOfMonth only goes up to 31 days.



              If you know these boundaries, you can 'hard code' them so that sql server knows what partitions to look for. After this you can add the extra filtering.



              E.G.



              WITH CTE
              AS
              (
              SELECT
              ai.Name
              ,dc.Component
              ,dc.Value
              ,dc.CalendarId
              ,ai.DayOfMonth
              FROM
              Warm.DailyCosts dc
              JOIN Warm.AccountInfo ai
              ON dc.AccountInfoId = ai.Id
              WHERE
              ai.CorrelationId = '00000000-0000-0000-0000-000000000000'
              AND ((dc.CalendarId >= (20190601 )
              AND dc.CalendarId < 20190701)
              OR (dc.CalendarId >= 20270601
              AND dc.CalendarId < (20270701)))

              )

              SELECT Name,Component,SUM(Value)
              FROM CTE
              WHERE ((CalendarId >= (20190601 + DayOfMonth - 1)
              AND CalendarId < 20190701)
              OR (CalendarId >= 20270601
              AND CalendarId < (20270601 + DayOfMonth - 1)))

              GROUP BY
              Name
              ,Component


              The sole purpose of the cte is to let sql server know that it can also filter on dc.CalendarId >= dc.CalendarId >= (20190601 ) OR dc.CalendarId < (20270701)).



              Sidenote: Adding a constraint does not work to enforce this.



              This query gives us the result we want, with the correct partition elemination:



              enter image description here



              enter image description here



              Only accessing partitions 19 & 21.



              You can probably also use OR / AND logic to get the same result if you prefer. The important part is getting the boundaries known.




              Test data



              CREATE SCHEMA WARM
              GO

              CREATE TABLE Warm.DailyCosts(ID INT IDENTITY(1,1) NOT NULL,
              Component int,
              Value int,
              CalendarId INT,
              AccountInfoId int
              )


              CREATE TABLE Warm.AccountInfo(Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
              Name VARCHAR(25),
              CorrelationId uniqueidentifier,
              DayOfMonth int
              );
              USE [master]
              GO
              ALTER DATABASE [test] ADD FILEGROUP [Partitionfg]
              GO
              USE [test]
              GO
              CREATE PARTITION FUNCTION [PF_CostDateByYearMonth](int) AS RANGE RIGHT FOR VALUES (
              20180101,
              20180201,
              20180301,
              20180401,
              20180501,
              20180601,
              20180701,
              20180801,
              20180901,
              20181001,
              20181101,
              20181201,
              20190101,
              20190201,
              20190301,
              20190401,
              20190501,
              20190601,
              20190701,
              20270601,
              20270701,
              20270801,
              20270901,
              20271001,
              20271101,
              20271201,
              20280101,
              20280201,
              20280301,
              20280401,
              20280501,
              20280601,
              20280701,
              20280801,
              20280901,
              20281001,
              20281101,
              20281201,
              20290101,
              20290201,
              20290301,
              20290401,
              20290501,
              20290601,
              20290701,
              20290801,
              20290901,
              20291001,
              20291101,
              20291201,
              20300101,
              20300201,
              20300301,
              20300401,
              20300501,
              20300601,
              20300701,
              20300801,
              20300901,
              20301001,
              20301101,
              20301201)


              CREATE PARTITION SCHEME [PS_CostDateByYearMonth]
              AS PARTITION [PF_CostDateByYearMonth]
              ALL TO ( [Partitionfg] );

              CREATE UNIQUE CLUSTERED INDEX ptci ON Warm.DailyCosts(CalendarId,Id) ON [PS_CostDateByYearMonth](CalendarId) ;
              USE [master]
              GO
              ALTER DATABASE [test] ADD FILE ( NAME = N'TestPartition', FILENAME = N'D:DATATestPartition.ndf' , SIZE = 3072KB , FILEGROWTH = 65536KB ) TO FILEGROUP [Partitionfg]
              GO
              USE [test]
              GO

              INSERT INTO Warm.DailyCosts(Component,
              Value,
              CalendarId,
              AccountInfoId
              )
              SELECT TOP(1000000) --1M
              ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
              ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
              20180101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
              ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
              FROM master..spt_values spt1
              CROSS APPLY master..spt_values spt2
              -- 2018
              INSERT INTO Warm.DailyCosts(Component,
              Value,
              CalendarId,
              AccountInfoId
              )
              SELECT TOP(1000000) --1M
              ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
              ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
              20190101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
              ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
              FROM master..spt_values spt1
              CROSS APPLY master..spt_values spt2
              -- 2019
              INSERT INTO Warm.DailyCosts(Component,
              Value,
              CalendarId,
              AccountInfoId
              )

              SELECT TOP(1000000) --1M
              ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
              ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
              20280101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
              ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
              FROM master..spt_values spt1
              CROSS APPLY master..spt_values spt2
              -- 2028

              INSERT INTO Warm.AccountInfo(
              Name ,
              CorrelationId,
              DayOfMonth
              )

              SELECT TOP(3000000) --3M
              CAST(ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS varchar(10)) + 'a',
              '00000000-0000-0000-0000-000000000000',
              15
              FROM master..spt_values spt1
              CROSS APPLY master..spt_values spt2
              CREATE NONCLUSTERED INDEX [IX_Component_Value_DailyCosts] ON Warm.DailyCosts
              (Component,Value)
              ON [PS_CostDateByYearMonth](CalendarId);
              GO





              share|improve this answer





























                9














                9










                9









                Reasoning



                When comparing the column of the non partitioned table against the partitioned table, sql server will not be able to know what DayOfMonth will hold, even if all of them are 15.



                As a result it would not know which partitions to return to satisfy this filtering when joining the two tables.



                A different example to give some more insight can be found here.




                Testing



                I was able to recreate your issue, for further questions please add as much information as possible.
                This could be Table definition, indexes, partition scheme, ...



                The DDL & DML is at the bottom.



                When running the query we can get the same result:



                enter image description here



                62 partitions returned.



                On the seek predicates it tries to filter what it can, this is the two filters on CalendarId that do not have the + DayOfMonth-1.



                enter image description here



                This translates to



                WHERE ...
                AND (( dc.CalendarId < 20190701)
                OR (dc.CalendarId >= 20270601))
                ...


                When running the query with these filters you will see the same amount of rows returned on accessing the table in the query plan.



                Only after getting this data, it can and will be joined to the AccountInfo table on the ID's and the DayOfMonth - 1



                enter image description here



                enter image description here



                To confirm your statement that when we remove the column that only two partitions are scanned:



                SELECT
                ai.Name
                ,SUM(dc.Component )
                ,SUM(dc.Value) Value
                FROM
                Warm.DailyCosts dc
                JOIN Warm.AccountInfo ai
                ON dc.AccountInfoId = ai.Id
                WHERE
                ai.CorrelationId = '00000000-0000-0000-0000-000000000000'
                AND ((dc.CalendarId >= (20190601 - 1)
                AND dc.CalendarId < 20190701)
                OR (dc.CalendarId >= 20270601
                AND dc.CalendarId < (20270601 - 1)))
                GROUP BY Name


                Only two are accessed and used:



                a




                Solution



                I am going to assume that DayOfMonth only goes up to 31 days.



                If you know these boundaries, you can 'hard code' them so that sql server knows what partitions to look for. After this you can add the extra filtering.



                E.G.



                WITH CTE
                AS
                (
                SELECT
                ai.Name
                ,dc.Component
                ,dc.Value
                ,dc.CalendarId
                ,ai.DayOfMonth
                FROM
                Warm.DailyCosts dc
                JOIN Warm.AccountInfo ai
                ON dc.AccountInfoId = ai.Id
                WHERE
                ai.CorrelationId = '00000000-0000-0000-0000-000000000000'
                AND ((dc.CalendarId >= (20190601 )
                AND dc.CalendarId < 20190701)
                OR (dc.CalendarId >= 20270601
                AND dc.CalendarId < (20270701)))

                )

                SELECT Name,Component,SUM(Value)
                FROM CTE
                WHERE ((CalendarId >= (20190601 + DayOfMonth - 1)
                AND CalendarId < 20190701)
                OR (CalendarId >= 20270601
                AND CalendarId < (20270601 + DayOfMonth - 1)))

                GROUP BY
                Name
                ,Component


                The sole purpose of the cte is to let sql server know that it can also filter on dc.CalendarId >= dc.CalendarId >= (20190601 ) OR dc.CalendarId < (20270701)).



                Sidenote: Adding a constraint does not work to enforce this.



                This query gives us the result we want, with the correct partition elemination:



                enter image description here



                enter image description here



                Only accessing partitions 19 & 21.



                You can probably also use OR / AND logic to get the same result if you prefer. The important part is getting the boundaries known.




                Test data



                CREATE SCHEMA WARM
                GO

                CREATE TABLE Warm.DailyCosts(ID INT IDENTITY(1,1) NOT NULL,
                Component int,
                Value int,
                CalendarId INT,
                AccountInfoId int
                )


                CREATE TABLE Warm.AccountInfo(Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
                Name VARCHAR(25),
                CorrelationId uniqueidentifier,
                DayOfMonth int
                );
                USE [master]
                GO
                ALTER DATABASE [test] ADD FILEGROUP [Partitionfg]
                GO
                USE [test]
                GO
                CREATE PARTITION FUNCTION [PF_CostDateByYearMonth](int) AS RANGE RIGHT FOR VALUES (
                20180101,
                20180201,
                20180301,
                20180401,
                20180501,
                20180601,
                20180701,
                20180801,
                20180901,
                20181001,
                20181101,
                20181201,
                20190101,
                20190201,
                20190301,
                20190401,
                20190501,
                20190601,
                20190701,
                20270601,
                20270701,
                20270801,
                20270901,
                20271001,
                20271101,
                20271201,
                20280101,
                20280201,
                20280301,
                20280401,
                20280501,
                20280601,
                20280701,
                20280801,
                20280901,
                20281001,
                20281101,
                20281201,
                20290101,
                20290201,
                20290301,
                20290401,
                20290501,
                20290601,
                20290701,
                20290801,
                20290901,
                20291001,
                20291101,
                20291201,
                20300101,
                20300201,
                20300301,
                20300401,
                20300501,
                20300601,
                20300701,
                20300801,
                20300901,
                20301001,
                20301101,
                20301201)


                CREATE PARTITION SCHEME [PS_CostDateByYearMonth]
                AS PARTITION [PF_CostDateByYearMonth]
                ALL TO ( [Partitionfg] );

                CREATE UNIQUE CLUSTERED INDEX ptci ON Warm.DailyCosts(CalendarId,Id) ON [PS_CostDateByYearMonth](CalendarId) ;
                USE [master]
                GO
                ALTER DATABASE [test] ADD FILE ( NAME = N'TestPartition', FILENAME = N'D:DATATestPartition.ndf' , SIZE = 3072KB , FILEGROWTH = 65536KB ) TO FILEGROUP [Partitionfg]
                GO
                USE [test]
                GO

                INSERT INTO Warm.DailyCosts(Component,
                Value,
                CalendarId,
                AccountInfoId
                )
                SELECT TOP(1000000) --1M
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
                20180101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
                FROM master..spt_values spt1
                CROSS APPLY master..spt_values spt2
                -- 2018
                INSERT INTO Warm.DailyCosts(Component,
                Value,
                CalendarId,
                AccountInfoId
                )
                SELECT TOP(1000000) --1M
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
                20190101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
                FROM master..spt_values spt1
                CROSS APPLY master..spt_values spt2
                -- 2019
                INSERT INTO Warm.DailyCosts(Component,
                Value,
                CalendarId,
                AccountInfoId
                )

                SELECT TOP(1000000) --1M
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
                20280101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
                FROM master..spt_values spt1
                CROSS APPLY master..spt_values spt2
                -- 2028

                INSERT INTO Warm.AccountInfo(
                Name ,
                CorrelationId,
                DayOfMonth
                )

                SELECT TOP(3000000) --3M
                CAST(ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS varchar(10)) + 'a',
                '00000000-0000-0000-0000-000000000000',
                15
                FROM master..spt_values spt1
                CROSS APPLY master..spt_values spt2
                CREATE NONCLUSTERED INDEX [IX_Component_Value_DailyCosts] ON Warm.DailyCosts
                (Component,Value)
                ON [PS_CostDateByYearMonth](CalendarId);
                GO





                share|improve this answer















                Reasoning



                When comparing the column of the non partitioned table against the partitioned table, sql server will not be able to know what DayOfMonth will hold, even if all of them are 15.



                As a result it would not know which partitions to return to satisfy this filtering when joining the two tables.



                A different example to give some more insight can be found here.




                Testing



                I was able to recreate your issue, for further questions please add as much information as possible.
                This could be Table definition, indexes, partition scheme, ...



                The DDL & DML is at the bottom.



                When running the query we can get the same result:



                enter image description here



                62 partitions returned.



                On the seek predicates it tries to filter what it can, this is the two filters on CalendarId that do not have the + DayOfMonth-1.



                enter image description here



                This translates to



                WHERE ...
                AND (( dc.CalendarId < 20190701)
                OR (dc.CalendarId >= 20270601))
                ...


                When running the query with these filters you will see the same amount of rows returned on accessing the table in the query plan.



                Only after getting this data, it can and will be joined to the AccountInfo table on the ID's and the DayOfMonth - 1



                enter image description here



                enter image description here



                To confirm your statement that when we remove the column that only two partitions are scanned:



                SELECT
                ai.Name
                ,SUM(dc.Component )
                ,SUM(dc.Value) Value
                FROM
                Warm.DailyCosts dc
                JOIN Warm.AccountInfo ai
                ON dc.AccountInfoId = ai.Id
                WHERE
                ai.CorrelationId = '00000000-0000-0000-0000-000000000000'
                AND ((dc.CalendarId >= (20190601 - 1)
                AND dc.CalendarId < 20190701)
                OR (dc.CalendarId >= 20270601
                AND dc.CalendarId < (20270601 - 1)))
                GROUP BY Name


                Only two are accessed and used:



                a




                Solution



                I am going to assume that DayOfMonth only goes up to 31 days.



                If you know these boundaries, you can 'hard code' them so that sql server knows what partitions to look for. After this you can add the extra filtering.



                E.G.



                WITH CTE
                AS
                (
                SELECT
                ai.Name
                ,dc.Component
                ,dc.Value
                ,dc.CalendarId
                ,ai.DayOfMonth
                FROM
                Warm.DailyCosts dc
                JOIN Warm.AccountInfo ai
                ON dc.AccountInfoId = ai.Id
                WHERE
                ai.CorrelationId = '00000000-0000-0000-0000-000000000000'
                AND ((dc.CalendarId >= (20190601 )
                AND dc.CalendarId < 20190701)
                OR (dc.CalendarId >= 20270601
                AND dc.CalendarId < (20270701)))

                )

                SELECT Name,Component,SUM(Value)
                FROM CTE
                WHERE ((CalendarId >= (20190601 + DayOfMonth - 1)
                AND CalendarId < 20190701)
                OR (CalendarId >= 20270601
                AND CalendarId < (20270601 + DayOfMonth - 1)))

                GROUP BY
                Name
                ,Component


                The sole purpose of the cte is to let sql server know that it can also filter on dc.CalendarId >= dc.CalendarId >= (20190601 ) OR dc.CalendarId < (20270701)).



                Sidenote: Adding a constraint does not work to enforce this.



                This query gives us the result we want, with the correct partition elemination:



                enter image description here



                enter image description here



                Only accessing partitions 19 & 21.



                You can probably also use OR / AND logic to get the same result if you prefer. The important part is getting the boundaries known.




                Test data



                CREATE SCHEMA WARM
                GO

                CREATE TABLE Warm.DailyCosts(ID INT IDENTITY(1,1) NOT NULL,
                Component int,
                Value int,
                CalendarId INT,
                AccountInfoId int
                )


                CREATE TABLE Warm.AccountInfo(Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
                Name VARCHAR(25),
                CorrelationId uniqueidentifier,
                DayOfMonth int
                );
                USE [master]
                GO
                ALTER DATABASE [test] ADD FILEGROUP [Partitionfg]
                GO
                USE [test]
                GO
                CREATE PARTITION FUNCTION [PF_CostDateByYearMonth](int) AS RANGE RIGHT FOR VALUES (
                20180101,
                20180201,
                20180301,
                20180401,
                20180501,
                20180601,
                20180701,
                20180801,
                20180901,
                20181001,
                20181101,
                20181201,
                20190101,
                20190201,
                20190301,
                20190401,
                20190501,
                20190601,
                20190701,
                20270601,
                20270701,
                20270801,
                20270901,
                20271001,
                20271101,
                20271201,
                20280101,
                20280201,
                20280301,
                20280401,
                20280501,
                20280601,
                20280701,
                20280801,
                20280901,
                20281001,
                20281101,
                20281201,
                20290101,
                20290201,
                20290301,
                20290401,
                20290501,
                20290601,
                20290701,
                20290801,
                20290901,
                20291001,
                20291101,
                20291201,
                20300101,
                20300201,
                20300301,
                20300401,
                20300501,
                20300601,
                20300701,
                20300801,
                20300901,
                20301001,
                20301101,
                20301201)


                CREATE PARTITION SCHEME [PS_CostDateByYearMonth]
                AS PARTITION [PF_CostDateByYearMonth]
                ALL TO ( [Partitionfg] );

                CREATE UNIQUE CLUSTERED INDEX ptci ON Warm.DailyCosts(CalendarId,Id) ON [PS_CostDateByYearMonth](CalendarId) ;
                USE [master]
                GO
                ALTER DATABASE [test] ADD FILE ( NAME = N'TestPartition', FILENAME = N'D:DATATestPartition.ndf' , SIZE = 3072KB , FILEGROWTH = 65536KB ) TO FILEGROUP [Partitionfg]
                GO
                USE [test]
                GO

                INSERT INTO Warm.DailyCosts(Component,
                Value,
                CalendarId,
                AccountInfoId
                )
                SELECT TOP(1000000) --1M
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
                20180101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
                FROM master..spt_values spt1
                CROSS APPLY master..spt_values spt2
                -- 2018
                INSERT INTO Warm.DailyCosts(Component,
                Value,
                CalendarId,
                AccountInfoId
                )
                SELECT TOP(1000000) --1M
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
                20190101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
                FROM master..spt_values spt1
                CROSS APPLY master..spt_values spt2
                -- 2019
                INSERT INTO Warm.DailyCosts(Component,
                Value,
                CalendarId,
                AccountInfoId
                )

                SELECT TOP(1000000) --1M
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
                20280101 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) / 1000 % 1000 ,
                ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
                FROM master..spt_values spt1
                CROSS APPLY master..spt_values spt2
                -- 2028

                INSERT INTO Warm.AccountInfo(
                Name ,
                CorrelationId,
                DayOfMonth
                )

                SELECT TOP(3000000) --3M
                CAST(ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS varchar(10)) + 'a',
                '00000000-0000-0000-0000-000000000000',
                15
                FROM master..spt_values spt1
                CROSS APPLY master..spt_values spt2
                CREATE NONCLUSTERED INDEX [IX_Component_Value_DailyCosts] ON Warm.DailyCosts
                (Component,Value)
                ON [PS_CostDateByYearMonth](CalendarId);
                GO






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Aug 19 at 12:24

























                answered Aug 17 at 0:31









                Randi VertongenRandi Vertongen

                8,1753 gold badges11 silver badges31 bronze badges




                8,1753 gold badges11 silver badges31 bronze badges






























                    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%2f245575%2fsql-server-query-scanning-more-partitions-than-expected%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

                    Get product attribute by attribute group code in magento 2get product attribute by product attribute group in magento 2Magento 2 Log Bundle Product Data in List Page?How to get all product attribute of a attribute group of Default attribute set?Magento 2.1 Create a filter in the product grid by new attributeMagento 2 : Get Product Attribute values By GroupMagento 2 How to get all existing values for one attributeMagento 2 get custom attribute of a single product inside a pluginMagento 2.3 How to get all the Multi Source Inventory (MSI) locations collection in custom module?Magento2: how to develop rest API to get new productsGet product attribute by attribute group code ( [attribute_group_code] ) in magento 2

                    Category:9 (number) SubcategoriesMedia in category "9 (number)"Navigation menuUpload mediaGND ID: 4485639-8Library of Congress authority ID: sh85091979ReasonatorScholiaStatistics

                    Magento 2.3: How do i solve this, Not registered handle, on custom form?How can i rewrite TierPrice Block in Magento2magento 2 captcha not rendering if I override layout xmlmain.CRITICAL: Plugin class doesn't existMagento 2 : Problem while adding custom button order view page?Magento 2.2.5: Overriding Admin Controller sales/orderMagento 2.2.5: Add, Update and Delete existing products Custom OptionsMagento 2.3 : File Upload issue in UI Component FormMagento2 Not registered handleHow to configured Form Builder Js in my custom magento 2.3.0 module?Magento 2.3. How to create image upload field in an admin form