{"id":680,"date":"2005-05-15T15:20:00","date_gmt":"2005-05-15T15:20:00","guid":{"rendered":"\/blogs\/kimberly\/post\/Clarifying-LEFT-and-RIGHT-in-the-defintion-of-a-PARTITION-FUNCTION-in-SQL-Server-2005.aspx"},"modified":"2013-01-11T23:13:47","modified_gmt":"2013-01-12T07:13:47","slug":"clarifying-left-and-right-in-the-defintion-of-a-partition-function-in-sql-server-2005","status":"publish","type":"post","link":"https:\/\/www.sqlskills.com\/blogs\/kimberly\/clarifying-left-and-right-in-the-defintion-of-a-partition-function-in-sql-server-2005\/","title":{"rendered":"Clarifying LEFT and RIGHT in the defintion of a PARTITION FUNCTION in SQL Server 2005"},"content":{"rendered":"<p>\n<strong>NOTE: <\/strong>Generally, I recommend RIGHT-based partition function so that&nbsp;you don&#39;t have to deal with datetime timetick issues at all. However, this post can really help you if you still want to use LEFT-based partition functions. Enjoy!!!&nbsp;\n<\/p>\n<p>\nWhen creating partitioned tables in SQL Server 2005, a partition function requires a LEFT or RIGHT designation. In general, I recommend that you choose to create a LEFT-based partition. However, choosing LEFT always creates some confusion because a left-based partition function requires upper boundaries. This results in a more complicated partition function definition (than a RIGHT partition function).\n<\/p>\n<p>\n<strong>Background First<\/strong><br \/>\nIn SQL Server 2005, you can create truly Partitioned Objects (objects are inclusive to Tables and Indexes) and to create a partitioned table you must base that table on a Partition Scheme (PS) and the PS must be based on a Partition Function (PF). Now, if you&#39;re new to the concept of partitioning, you should seriously consider reading the whitepaper I wrote for MSDN which is posted <a href=\"http:\/\/msdn.microsoft.com\/library\/default.asp?url=\/library\/en-us\/dnsql90\/html\/sql2k5partition.asp\">here<\/a>.\n<\/p>\n<p>\nRegardless of your having read the whitepaper, I want to add a few basic principles and make sure that some of the key points are clear. Simply put, a PF is the logical definition of your boundary cases (or possibly better described as the intervals over which each partition covers).&nbsp;A PF must cover the entire domain from negative infinity to positive infinity. If a value doesn&#39;t have a place to go then you&#39;d have a problem with the logic of your partition function. Having said that, when you define the PF you are ONLY stating values, not where they will physically will reside. Futhermore, the expression on which the data will be based has to be somewhat straightforward and consistent. In other words, simple. If the PF were extremely complex it could compromise the usage and performance of the Partitioned Object. Finally, the definition of the PF is really just a way to easily define these boundaries. As a result, you can choose to enter a specific value (like June 1, 2005) or a function like the following to create a PF over 4 months with each month being computed from current:\n<\/p>\n<p>\nCREATE PARTITION FUNCTION TestFunctionValues(datetime)<br \/>\nAS<br \/>\nRANGE RIGHT FOR VALUES (<br \/>\n&nbsp;&nbsp;&nbsp;CONVERT(char(4), year(dateadd(m, 1, getdate()))) + right(&#39;0&#39; + convert(char(1), month(dateadd(m, 1, getdate()))), 2) + &#39;01&#39;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8212; next month (executed in May, 2005 yields June 2005)<br \/>\n&nbsp;&nbsp;&nbsp;, CONVERT(char(4), year(dateadd(m, 2, getdate()))) + right(&#39;0&#39; + convert(char(1), month(dateadd(m, 2, getdate()))), 2) + &#39;01&#39;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8212; executed in May, 2005 yields July 2005<br \/>\n&nbsp;&nbsp;&nbsp;, CONVERT(char(4), year(dateadd(m, 3, getdate()))) + right(&#39;0&#39; + convert(char(1), month(dateadd(m, 3, getdate()))), 2) + &#39;01&#39;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8212; executed in May, 2005 yields August 2005<br \/>\n&nbsp;&nbsp;&nbsp;, CONVERT(char(4), year(dateadd(m, 4, getdate()))) + right(&#39;0&#39; + convert(char(1), month(dateadd(m, 4, getdate()))), 2) + &#39;01&#39;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8212; executed in May, 2005 yields September 2005<br \/>\n)<br \/>\nGO\n<\/p>\n<p>\nSince all of these complex expressions are evaluated to a constant at creation, you can immediately verify your boundary cases by accessing some catalog views. Here is the catalog view query which helps you see what your partition boundaries are:\n<\/p>\n<p>\nSELECT PF.[name], RV.boundary_id, RV.[value]<br \/>\nFROM sys.partition_range_values AS RV<br \/>\n&nbsp;JOIN sys.partition_functions AS PF<br \/>\n&nbsp;&nbsp;ON RV.function_id = PF.function_id<br \/>\nWHERE PF.[name] = &#39;TestFunctionValues&#39;\n<\/p>\n<p>\nIn the above partition function, you&#39;ll notice that in addition to the values, I also have a RIGHT designation. The choice of using RIGHT, helps to target whether or not the value is a member of the first partition or the second partition. In the case of RIGHT, this says that the value is a lower boundary of the second partition. In an example that involves something like &quot;sales&quot; where data rows are ever increasing and their usage is for more recent rather than older data you migth want to always have the most recent four months of data available (in the real world you&#39;d probably want more than 4 months but I&#39;m going to simplify to four so that we have fewer boundaries with which to work). So, if we want 4 partitions &#8211; one for June, July, August and September &#8211; we need to define the partitions in the form of intervals (using boundaries). The first boundary point will either reside in the first partition (as an upper boundary) or the second partition (as a lower boundary). For four partitions, there are numerous ways in which&nbsp;you could define the partition function such that the logical\/physical placement of the data is THE SAME however, the behavior of the partition function during later SPLIT and MERGE operations is also impacted by the choice of LEFT\/RIGHT so understanding how they work is critical in making your decision to use one or the other. More than anything, will need to respect the full domain from negative infinity to positive infinity.\n<\/p>\n<p>\nThe following partition function is one of the easiest and most logical to understand. We need four partitions so let&#39;s just enter our boundary points and be done.\n<\/p>\n<p>\nCREATE PARTITION FUNCTION RightPartitionFunction1(datetime)<br \/>\nAS<br \/>\nRANGE RIGHT FOR VALUES (<br \/>\n&nbsp;&nbsp;&nbsp;&#39;20040601&#39;,&nbsp;&#8212; Jun 2004<br \/>\n&nbsp;&nbsp;&nbsp;&#39;20040701&#39;,&nbsp;&#8212; Jul 2004<br \/>\n&nbsp;&nbsp;&nbsp;&#39;20040801&#39;,&nbsp;&#8212; Aug 2004<br \/>\n&nbsp;&nbsp;&nbsp;&#39;20040901&#39;&nbsp;&#8212; Sep 2004<br \/>\n)\n<\/p>\n<p>\nHowever, remember that we have the full domain to cover. As a result, the above partition function will create 5 partitions where the partitions will be:<br \/>\n&nbsp;Partition 1: all data less than 20040601<br \/>\n&nbsp;Partition 2: all data greater then\/equal to 20040601 and less than 20040701<br \/>\n&nbsp;Partition 3: all data greater then\/equal to 20040701 and less than 20040801<br \/>\n&nbsp;Partition 4: all data greater then\/equal to 20040801 and less than 20040901<br \/>\n&nbsp;Partition 5: all data greater then\/equal to 20040901\n<\/p>\n<p>\nThis really isn&#39;t too bad but it seems to waste the first partition because it&#39;s completely empty&#8230; so, you could remove the first boundary point and just supply the second, third and forth. In that case, the first partition would cover June (instead of being empty) and you could get down to 4 partitions with only 3 boundary points.\n<\/p>\n<p>\nCREATE PARTITION FUNCTION RightPartitionFunction2(datetime)<br \/>\nAS<br \/>\nRANGE RIGHT FOR VALUES (<br \/>\n&nbsp;&nbsp;&nbsp;&#39;20040701&#39;,&nbsp;&#8212; Jul 2004<br \/>\n&nbsp;&nbsp;&nbsp;&#39;20040801&#39;,&nbsp;&#8212; Aug 2004<br \/>\n&nbsp;&nbsp;&nbsp;&#39;20040901&#39;&nbsp;&#8212; Sep 2004<br \/>\n)\n<\/p>\n<p>\nThis will create 4 partitions where the partitions will be:<br \/>\n&nbsp;Partition 1: all data less than 20040701<br \/>\n&nbsp;Partition 2: all data greater then\/equal to 20040701 and less than 20040801<br \/>\n&nbsp;Partition 3: all data greater then\/equal to 20040801 and less than 20040901<br \/>\n&nbsp;Partition 4: all data greater then\/equal to 20040901\n<\/p>\n<p>\nOK, so this seems a bit more optimal. And by definition alone, I would agree with you. Where it becomes problematic is in the merge and split operations. When a partition function goes through a merge of a boundary point, that boundary point is essentially removed. This seems simple but also has an impact on the data which resides in that partition (the partition which includes that boundary point). So, if this partitioned table is NEVER going to be modified and you never need to plan for a merge or split, then you can choose whatever definition is easier for you to use. However, if you plan to do a merge or split, you need to understand the ramifications of the LEFT\/RIGHT decision. If November 1 comes around and you want the data for October to be added to your partitioned table and you ONLY want to show the most four months, then you will need to add October and remove June. The process will essentially consist of the following:\n<\/p>\n<ol>\n<li>Create a place for new data (Oct) to reside <\/li>\n<li>Add this location to the partition scheme (more details on the scheme v. the function shortly) <\/li>\n<li>Split the last boundary to add the new month (Oct) <\/li>\n<li>Switch-in the staging table of October data so it becomes part of the partitioned table <\/li>\n<li>Create a staging table into which the old data (Jun) will go <\/li>\n<li>Switch-out the June data into the staging table <\/li>\n<li>Merge the boundary point to remove June from the table<\/li>\n<\/ol>\n<p>\n<strong>More background first &#8211; Partition Schemes<br \/>\n<\/strong>You will want to have a place to put the new data (there are lots of things we could look at here&#8230; do you want to ALWAYS only use 4 filegroups and when you remove June&#39;s data do you want to reuse that space &#8211; or do you have a new location on which October can be placed). This is a whole different topic over which we should chat&#8230; but for simplicity let&#39;s just say that we want to use a new location. To tell the PF where this location is, you need to work with the physical definition of the partition function. OK, that might not be clear. So far, I&#39;ve only told you about the PF and so far, I&#39;ve only said that the PF described the logical boudaries. You may have been wondering how SQL Server maps these logical boundaries to the phyiscal files and the answer is through the Partition Scheme. The partition scheme (at initial creation) sets up the mapping of the boundaries to their phyiscal locations (through filegroups). For the first and second PFs created above the respective partition schemes would be:\n<\/p>\n<p>\nCREATE PARTITION SCHEME [PartitionScheme1]<br \/>\nAS<br \/>\nPARTITION [RightPartitionFunction1] TO <br \/>\n&nbsp;&nbsp;( [Primary]&nbsp;&nbsp;&nbsp; &#8212; should be empty?<br \/>\n&nbsp;&nbsp;, [PartitionedTablesFG1]&nbsp; &#8212; for June<br \/>\n&nbsp;&nbsp;, [PartitionedTablesFG2]&nbsp; &#8212; for July<br \/>\n&nbsp;&nbsp;, [PartitionedTablesFG3]&nbsp; &#8212; for Aug<br \/>\n&nbsp;&nbsp;, [PartitionedTablesFG4]&nbsp; &#8212; for Sept<br \/>\n&nbsp;&nbsp;)<br \/>\nand\/or\n<\/p>\n<p>\nCREATE PARTITION SCHEME [PartitionScheme2]<br \/>\nAS<br \/>\nPARTITION [RightPartitionFunction2] TO <br \/>\n&nbsp;&nbsp;( [PartitionedTablesFG1]&nbsp; &#8212; for June<br \/>\n&nbsp;&nbsp;, [PartitionedTablesFG2]&nbsp; &#8212; for July<br \/>\n&nbsp;&nbsp;, [PartitionedTablesFG3]&nbsp; &#8212; for Aug<br \/>\n&nbsp;&nbsp;, [PartitionedTablesFG4]) &#8212; for Sept\n<\/p>\n<p>\nIn both cases, it seems as though these do the same thing with the exception that the first PF ends up with an extra partition which is essentially empty. In <strong>this <\/strong>case (in a RIGHT-based PF), the second is a better choice (coming up there will be a reason for why we create an empty partition).\n<\/p>\n<p>\n<strong>Back to SPLIT and MERGE<br \/>\n<\/strong>OK, so back to the issue of spliting and merging. Our goal is to remove June and add October so that the &quot;current&quot; data shows the four months of July, Aug, Sept and Oct. If we want to create a location on which October can be placed, we need to add another filegroup to the scheme. The way we do this is that we first need to add the filegroup\/file to the database and then we need to add this new filegroup to our partition scheme.\n<\/p>\n<p>\n<strong>Step 1 &#8211; Create a place for new data (Oct) to reside<br \/>\n<\/strong>Create a new filegroup and new file.\n<\/p>\n<p>\nALTER DATABASE CreditPT <br \/>\n&nbsp;ADD FILEGROUP PartitionedTablesFG5<br \/>\nGO\n<\/p>\n<p>\nALTER DATABASE CreditPT <br \/>\n&nbsp;ADD FILE<br \/>\n&nbsp;&nbsp;(NAME = N&#39;CreditPTFG5File1&#39;, <br \/>\n&nbsp;&nbsp;FILENAME = N&#39;C:\\SQLTemp\\CreditPTFG5File1.ndf&#39;, <br \/>\n&nbsp;&nbsp;SIZE = 30, FILEGROWTH = 10, MAXSIZE = 50) <br \/>\n&nbsp;&nbsp;TO FILEGROUP [PartitionedTablesFG5]<br \/>\nGO\n<\/p>\n<p>\n<strong>Step 2 &#8211; Add this location to the partition scheme<br \/>\n<\/strong>The way to do this is to add a &quot;NEXT USED&quot; filegroup. Syntax:\n<\/p>\n<p>\nALTER PARTITION SCHEME PartitionScheme2 NEXT USED [PartitionedTablesFG5]<br \/>\nGO\n<\/p>\n<div>\nOnce the partition scheme has a new filegroup to use (and you can only have one at a time &#8211; note that if you add a second it solely replaces the first and does not warn you that you already had a next used), then the next time a partition is needed (which will be on the next split) then this &quot;next used&quot; partition will be used.\n<\/div>\n<p>\n<strong>Step 3 &#8211; Split the last boundary to add the new month (Oct)<br \/>\n<\/strong>Now that we have a filegroup AND we have told the partition scheme to use it for the next split operation, we can split the PS to include this 5th filegroup\n<\/p>\n<p>\nALTER PARTITION FUNCTION RightPartitionFunction2() <br \/>\nSPLIT RANGE (&#39;20041001&#39;)<br \/>\nGO\n<\/p>\n<p>\n<strong>Step 4 &#8211; Switch-in the staging table of October data so it becomes part of the partitioned table<br \/>\n<\/strong>This step really needs more to it. To switch in your staging table you need to already have a staging table. To make this an optimal operation, you MUST create your staging table on the same fielgroup on which the partition will reside. What you&#39;re trying to do is make the switch optimal by making it a metadata only operation. This step really consists of creating an identical table with identical indexes and creating it with a constraint that matches the partitions&#39; definition (so that SQL Server can trust&nbsp;that it only includes data within the interval for that partition).\n<\/p>\n<p>\nCREATE TABLE ChargesPTRightOct<br \/>\n( &nbsp;charge_no&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;NOT NULL&nbsp;IDENTITY,<br \/>\n&nbsp;member_no&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;NOT NULL<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONSTRAINT ChargesPTRightOctMemberNoFK<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;REFERENCES dbo.Member(Member_No),<br \/>\n&nbsp;provider_no&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;NOT NULL<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONSTRAINT ChargesPTRightOctProviderNoFK<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;REFERENCES dbo.Provider(Provider_No),<br \/>\n&nbsp;category_no&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;NOT NULL<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONSTRAINT ChargesPTRightOctCategoryNoFK<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;REFERENCES dbo.Category(Category_No),<br \/>\n&nbsp;charge_dt&nbsp;&nbsp;datetime &nbsp;NOT NULL<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONSTRAINT ChargesPTRightOctChargeDtCK<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CHECK (Charge_dt &gt;= &#39;20041001&#39; <br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AND Charge_dt &lt; &#39;20041101&#39;),<br \/>\n&nbsp;charge_amt&nbsp;&nbsp;money&nbsp;&nbsp;NOT NULL,<br \/>\n&nbsp;statement_no&nbsp;int&nbsp;&nbsp;&nbsp;NOT NULL,<br \/>\n&nbsp;charge_code&nbsp;&nbsp;char(2)&nbsp;&nbsp;NOT NULL<br \/>\n) ON [PartitionedTablesFG5]<br \/>\nGO\n<\/p>\n<p>\nALTER TABLE ChargesPTRightOct<br \/>\nADD CONSTRAINT ChargesPTRightOctPK<br \/>\n&nbsp;&nbsp;PRIMARY KEY CLUSTERED (charge_dt, charge_no) <br \/>\n&#8212;&nbsp;&nbsp;&nbsp;ON Credit4MonthPFN (charge_dt)<br \/>\nGO\n<\/p>\n<p>\nINSERT ChargesPTRightOct (member_no, provider_no, category_no<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;, charge_dt, charge_amt<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;, statement_no, charge_code)<br \/>\n&nbsp;SELECT member_no, provider_no, category_no<br \/>\n&nbsp;&nbsp;&nbsp;, dateadd(yy, 5, charge_dt), (charge_amt + charge_no)\/10<br \/>\n&nbsp;&nbsp;&nbsp;, statement_no, charge_code <br \/>\n&nbsp;FROM CreditPT.dbo.Charge<br \/>\n&nbsp;WHERE month(charge_dt) IN (10)<br \/>\n&nbsp;ORDER BY charge_dt, charge_no<br \/>\nGO\n<\/p>\n<p>\nALTER TABLE ChargesPTRightOct <br \/>\nSWITCH TO ChargesPTRight PARTITION 5<br \/>\nGO\n<\/p>\n<p>\n<strong>Step 5 &#8211; Create a staging table into which the old data (Jun) will go<br \/>\n<\/strong>Similarly, you will want to create a place for the June data to go &#8211; kind of like a &ldquo;staging&rdquo; table but more for the exit of the table.\n<\/p>\n<p>\nCREATE TABLE ChargesPTRightJun<br \/>\n( &nbsp;charge_no&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;NOT NULL&nbsp;IDENTITY,<br \/>\n&nbsp;member_no&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;NOT NULL<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONSTRAINT ChargesPTRightJunMemberNoFK<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;REFERENCES dbo.Member(Member_No),<br \/>\n&nbsp;provider_no&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;NOT NULL<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONSTRAINT ChargesPTRightJunProviderNoFK<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;REFERENCES dbo.Provider(Provider_No),<br \/>\n&nbsp;category_no&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;NOT NULL<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONSTRAINT ChargesPTRightJunCategoryNoFK<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;REFERENCES dbo.Category(Category_No),<br \/>\n&nbsp;charge_dt&nbsp;&nbsp;datetime &nbsp;NOT NULL,<br \/>\n&nbsp;charge_amt&nbsp;&nbsp;money&nbsp;&nbsp;NOT NULL,<br \/>\n&nbsp;statement_no&nbsp;int&nbsp;&nbsp;&nbsp;NOT NULL,<br \/>\n&nbsp;charge_code&nbsp;&nbsp;char(2)&nbsp;&nbsp;NOT NULL<br \/>\n) ON [PartitionedTablesFG1]<br \/>\nGO\n<\/p>\n<p>\nALTER TABLE ChargesPTRightJun<br \/>\nADD CONSTRAINT ChargesPTRightJunPK<br \/>\n&nbsp;&nbsp;PRIMARY KEY CLUSTERED (charge_dt, charge_no) <br \/>\n&#8212;&nbsp;&nbsp;&nbsp;ON Credit4MonthPFN (charge_dt)<br \/>\nGO\n<\/p>\n<p>\n<strong>Step 6 &#8211; Switch-out the June data into the staging table<br \/>\n<\/strong>This must also be a metadata only step. You need to make sure that it&#39;s created on the same filegroup as where the data currently resides (see the ON [ParitionedTablesFG1] clause. This is the current location of this partition. As a result, the switch out will be very fast.\n<\/p>\n<p>\nALTER TABLE ChargesPTRight<br \/>\nSWITCH PARTITION 1<br \/>\nTO ChargesPTRightJun<br \/>\nGO\n<\/p>\n<p>\n<strong>Step 7 &#8211; Merge the boundary point to remove June from the table<br \/>\n<\/strong>This last step is the whole reason for this blog entry&#8230; yes, we&#39;re getting there ;).\n<\/p>\n<p>\nALTER PARTITION FUNCTION RightPartitionFunction2()<br \/>\nMERGE RANGE (&#39;20040701&#39;)<br \/>\nGO\n<\/p>\n<p>\nWhen you merge this boundary point, you will remove the value AND the parition in which it resides. Since this boundary point resides in the second partition (PartitionedTablesFG2) then it&#39;s actually PartitionedTablesFG2 that gets removed. As a result ALL of the data that resides on it, must be moved to the filegroup that now covers this boundary (which is PartitionedTablesFG1 and which was just emptied). As a result, MERGE does NOT optimally merge with a RIGHT-based partition on the rolling range scenario.\n<\/p>\n<p>\nAnd &#8211; as a result, I recommend LEFT-based partition functions&#8230;&nbsp;Since the whitepaper tends to focus on using LEFT-based parition functions, please review that for more details. You can access the &ldquo;Paritioned Tables&rdquo; whitepaper on MSDN, <a href=\"http:\/\/msdn.microsoft.com\/library\/default.asp?url=\/library\/en-us\/dnsql90\/html\/sql2k5partition.asp\">here<\/a>.\n<\/p>\n<p>\nHope this helps and thanks for reading!<br \/>\nkt<\/p>\n","protected":false},"excerpt":{"rendered":"<p>NOTE: Generally, I recommend RIGHT-based partition function so that&nbsp;you don&#39;t have to deal with datetime timetick issues at all. However, this post can really help you if you still want to use LEFT-based partition functions. Enjoy!!!&nbsp; When creating partitioned tables in SQL Server 2005, a partition function requires a LEFT or RIGHT designation. In general, [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[25,27,49,51,65,78],"tags":[],"class_list":["post-680","post","type-post","status-publish","format-standard","hentry","category-design","category-events","category-opinions","category-partitioning","category-sql-server-2005","category-tips"],"_links":{"self":[{"href":"https:\/\/www.sqlskills.com\/blogs\/kimberly\/wp-json\/wp\/v2\/posts\/680","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqlskills.com\/blogs\/kimberly\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqlskills.com\/blogs\/kimberly\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/kimberly\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/kimberly\/wp-json\/wp\/v2\/comments?post=680"}],"version-history":[{"count":0,"href":"https:\/\/www.sqlskills.com\/blogs\/kimberly\/wp-json\/wp\/v2\/posts\/680\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.sqlskills.com\/blogs\/kimberly\/wp-json\/wp\/v2\/media?parent=680"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/kimberly\/wp-json\/wp\/v2\/categories?post=680"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/kimberly\/wp-json\/wp\/v2\/tags?post=680"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}