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

The space of cusp forms for GL_2 over F_q(T)

How to mock ApexTestQueueItem, AsyncApexJob, and ApexTestResult for test coverage?

A Magic Diamond

Attacking the Hydra

Airline power sockets shut down when I plug my computer in. How can I avoid that?

What is the question mark?

Unconventional examples of mathematical modelling

How does the Moon's gravity affect Earth's oceans despite Earth's stronger gravitational pull?

What exactly happened to the 18 crew members who were reported as "missing" in "Q Who"?

Why is the battery jumpered to a resistor in this schematic?

Why does "auf der Strecke bleiben" mean "to fall by the wayside"?

Deciphering Lunacy Asylum case notes about General appearance / Description of Bodily Symptoms

What allows us to use imaginary numbers?

Can anybody tell me who this Pokemon is?

What is the opposite of "hunger level"?

Is there a way, other than having a Diviner friend, for a player to avoid rolling Initiative at the start of a combat?

Have there ever been other TV shows or Films that told a similiar story to the new 90210 show?

Units of measurement, especially length, when body parts vary in size among races

Why do we use low resistance cables to minimize power losses?

What are some tips and tricks for finding the cheapest flight when luggage and other fees are not revealed until far into the booking process?

Java methods to add and authenticate users in MySQL

String routines

Would getting a natural 20 with a penalty still count as a critical hit?

Who owns content posted at Paizo.com forums?



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;








3















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







New contributor



Ben is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.



























    3















    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







    New contributor



    Ben is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.























      3












      3








      3








      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







      New contributor



      Ben is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      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







      New contributor



      Ben is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.










      share|improve this question







      New contributor



      Ben is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.








      share|improve this question




      share|improve this question






      New contributor



      Ben is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.








      asked 8 hours ago









      BenBen

      161 bronze badge




      161 bronze badge




      New contributor



      Ben is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.




      New contributor




      Ben is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.

























          1 Answer
          1






          active

          oldest

          votes


















          3














          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



          And to confirm when we change the query:



          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


          It does eleminate partitions:



          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.




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



            );






            Ben is a new contributor. Be nice, and check out our Code of Conduct.









            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









            3














            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



            And to confirm when we change the query:



            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


            It does eleminate partitions:



            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.




            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































              3














              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



              And to confirm when we change the query:



              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


              It does eleminate partitions:



              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.




              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





























                3












                3








                3







                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



                And to confirm when we change the query:



                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


                It does eleminate partitions:



                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.




                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



                And to confirm when we change the query:



                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


                It does eleminate partitions:



                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.




                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 5 hours ago

























                answered 5 hours ago









                Randi VertongenRandi Vertongen

                7,8453 gold badges10 silver badges31 bronze badges




                7,8453 gold badges10 silver badges31 bronze badges























                    Ben is a new contributor. Be nice, and check out our Code of Conduct.









                    draft saved

                    draft discarded


















                    Ben is a new contributor. Be nice, and check out our Code of Conduct.












                    Ben is a new contributor. Be nice, and check out our Code of Conduct.











                    Ben is a new contributor. Be nice, and check out our Code of Conduct.














                    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

                    Invision Community Contents History See also References External links Navigation menuProprietaryinvisioncommunity.comIPS Community ForumsIPS Community Forumsthis blog entry"License Changes, IP.Board 3.4, and the Future""Interview -- Matt Mecham of Ibforums""CEO Invision Power Board, Matt Mecham Is a Liar, Thief!"IPB License Explanation 1.3, 1.3.1, 2.0, and 2.1ArchivedSecurity Fixes, Updates And Enhancements For IPB 1.3.1Archived"New Demo Accounts - Invision Power Services"the original"New Default Skin"the original"Invision Power Board 3.0.0 and Applications Released"the original"Archived copy"the original"Perpetual licenses being done away with""Release Notes - Invision Power Services""Introducing: IPS Community Suite 4!"Invision Community Release Notes

                    Canceling a color specificationRandomly assigning color to Graphics3D objects?Default color for Filling in Mathematica 9Coloring specific elements of sets with a prime modified order in an array plotHow to pick a color differing significantly from the colors already in a given color list?Detection of the text colorColor numbers based on their valueCan color schemes for use with ColorData include opacity specification?My dynamic color schemes

                    Ласкавець круглолистий Зміст Опис | Поширення | Галерея | Примітки | Посилання | Навігаційне меню58171138361-22960890446Bupleurum rotundifoliumEuro+Med PlantbasePlants of the World Online — Kew ScienceGermplasm Resources Information Network (GRIN)Ласкавецькн. VI : Літери Ком — Левиправивши або дописавши її