{"id":699,"date":"2008-04-08T17:50:00","date_gmt":"2008-04-08T17:50:00","guid":{"rendered":"\/blogs\/bobb\/post\/Converting-an-EAV-design-to-sparse-columns-and-populating.aspx"},"modified":"2008-04-08T17:50:00","modified_gmt":"2008-04-08T17:50:00","slug":"converting-an-eav-design-to-sparse-columns-and-populating","status":"publish","type":"post","link":"https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/","title":{"rendered":"Converting an EAV design to sparse columns and populating"},"content":{"rendered":"<p>\nOne of the uses for sparse columns will likely be replacing entity-attribute-value designs. In an EAV design, the &quot;sparse attribute&quot; values are represented by a separate table. The attribute value can either be declared as (n)varchar or sql_variant. An example I&#39;ve always used is the hardware store that wants to keep track of its products in a &quot;products&quot; table, but each product has different attributes. If you use the minimum number of columns to simplify the example, the EAV design looks like this.\n<\/p>\n<p>\ncreate table products &#8212; base table<br \/>\n(<br \/>\n&nbsp;id int primary key,<br \/>\n&nbsp;name varchar(max)<br \/>\n)<br \/>\ngo<br \/>\ncreate table properties &#8212; sparse attribute (name-value pair) table<br \/>\n(<br \/>\n&nbsp;id int,<br \/>\n&nbsp;name varchar(50),<br \/>\n&nbsp;value varchar(max),<br \/>\n&nbsp;CONSTRAINT PK_properties PRIMARY KEY (id, name),<br \/>\n&nbsp;FOREIGN KEY (id) REFERENCES&nbsp;products (id)<br \/>\n)<br \/>\ngo\n<\/p>\n<p>\nHere&#39;s a straightforward way to convert the table to use SQL Server 2008&#39;s sparse columns. It uses dynamic SQL, but in this case there&#39;s no user input (SQL injection worries).\n<\/p>\n<p>\ndeclare @tab nvarchar(max), <br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @sql nvarchar(max)\n<\/p>\n<p>\nset @tab=N&#39;create table products2 (id int primary key, name nvarchar(max) &#39;<br \/>\nselect&nbsp; @tab=@tab+&#39;,&#39;+ name + &#39; varchar(max) sparse&#39; from properties <br \/>\ngroup by name <br \/>\nset @tab += &#39; ,col_values xml column_set for all_sparse_columns);&#39;<br \/>\n&#8212; select @tab<br \/>\nexec(@tab)\n<\/p>\n<p>\nPopulating it is also straghtforward using the pivot operator, introduced in SQL Server 2005. In the case where each item has only one of each sparse property (the table constraint enforces this), and our properties table has only three columns, there&#39;s no real aggregation with pivot. The aggregate is just required by the pivot operator syntax. This populates the table:\n<\/p>\n<p>\ndeclare @col nvarchar(max), <br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @sql nvarchar(max)\n<\/p>\n<p>\nset @cols=N&#39;&#39;<br \/>\nselect&nbsp; @cols=@cols+&#39;,&#39;+ name from properties <br \/>\ngroup by name <br \/>\n&nbsp;select @cols<br \/>\nset @cols=substring(@cols,2,datalength(@cols)\/2 &#8211; 1)<br \/>\nset @sql=N&#39;insert into products2 (id, name,&#39; + @cols + &#39;) select p.id, p.name, <a href=\"mailto:'+@cols\">&#39;+@cols<\/a>+<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; N&#39; from (<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; select id, name, value <br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from properties<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ) as q<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pivot<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max(value)<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for name in (<a href=\"mailto:'+@cols\">&#39;+@cols<\/a>+<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#39;)<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ) as PivotTable&#39;<br \/>\nset @sql += &#39; join products p on PivotTable.id = p.id&#39;<br \/>\n&#8212; select @sql<br \/>\nexec (@sql)\n<\/p>\n<p>\nWhat remains to be done now is to choose better data types for the sparse columns, if the data isn&#39;t really a string. If you haven&#39;t enforced value type correctness in the application, this may require some data cleansing. Full example as an attachment. Remember that currently (in CTP6) you can only have 1024 total columns in a table; but the limit will be increased to 30000 sparse columns&nbsp;before RTM.\n<\/p>\n<p><a href=\"\/blogs\/bobb\/content\/binary\/eav_to_sparse.zip\">eav_to_sparse.zip (1.23 KB)<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the uses for sparse columns will likely be replacing entity-attribute-value designs. In an EAV design, the &quot;sparse attribute&quot; values are represented by a separate table. The attribute value can either be declared as (n)varchar or sql_variant. An example I&#39;ve always used is the hardware store that wants to keep track of its products [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26,29],"tags":[],"class_list":["post-699","post","type-post","status-publish","format-standard","hentry","category-sparse-columns","category-sql-server-2008"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.9.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Converting an EAV design to sparse columns and populating - Bob Beauchemin<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Converting an EAV design to sparse columns and populating - Bob Beauchemin\" \/>\n<meta property=\"og:description\" content=\"One of the uses for sparse columns will likely be replacing entity-attribute-value designs. In an EAV design, the &quot;sparse attribute&quot; values are represented by a separate table. The attribute value can either be declared as (n)varchar or sql_variant. An example I&#039;ve always used is the hardware store that wants to keep track of its products [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/\" \/>\n<meta property=\"og:site_name\" content=\"Bob Beauchemin\" \/>\n<meta property=\"article:published_time\" content=\"2008-04-08T17:50:00+00:00\" \/>\n<meta name=\"author\" content=\"Bob Beauchemin\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Bob Beauchemin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/\",\"name\":\"Converting an EAV design to sparse columns and populating - Bob Beauchemin\",\"isPartOf\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website\"},\"datePublished\":\"2008-04-08T17:50:00+00:00\",\"dateModified\":\"2008-04-08T17:50:00+00:00\",\"author\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Sparse Columns\",\"item\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/category\/sparse-columns\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Converting an EAV design to sparse columns and populating\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/\",\"name\":\"Bob Beauchemin\",\"description\":\"SQL Server Blog\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e\",\"name\":\"Bob Beauchemin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g\",\"caption\":\"Bob Beauchemin\"},\"sameAs\":[\"http:\/www.sqlskills.com\/blogs\/bobb\/\"],\"url\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/author\/bobb\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Converting an EAV design to sparse columns and populating - Bob Beauchemin","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/","og_locale":"en_US","og_type":"article","og_title":"Converting an EAV design to sparse columns and populating - Bob Beauchemin","og_description":"One of the uses for sparse columns will likely be replacing entity-attribute-value designs. In an EAV design, the &quot;sparse attribute&quot; values are represented by a separate table. The attribute value can either be declared as (n)varchar or sql_variant. An example I&#39;ve always used is the hardware store that wants to keep track of its products [&hellip;]","og_url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/","og_site_name":"Bob Beauchemin","article_published_time":"2008-04-08T17:50:00+00:00","author":"Bob Beauchemin","twitter_misc":{"Written by":"Bob Beauchemin","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/","url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/","name":"Converting an EAV design to sparse columns and populating - Bob Beauchemin","isPartOf":{"@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website"},"datePublished":"2008-04-08T17:50:00+00:00","dateModified":"2008-04-08T17:50:00+00:00","author":{"@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e"},"breadcrumb":{"@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/converting-an-eav-design-to-sparse-columns-and-populating\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.sqlskills.com\/blogs\/bobb\/"},{"@type":"ListItem","position":2,"name":"Sparse Columns","item":"https:\/\/www.sqlskills.com\/blogs\/bobb\/category\/sparse-columns\/"},{"@type":"ListItem","position":3,"name":"Converting an EAV design to sparse columns and populating"}]},{"@type":"WebSite","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website","url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/","name":"Bob Beauchemin","description":"SQL Server Blog","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.sqlskills.com\/blogs\/bobb\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e","name":"Bob Beauchemin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g","caption":"Bob Beauchemin"},"sameAs":["http:\/www.sqlskills.com\/blogs\/bobb\/"],"url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/author\/bobb\/"}]}},"_links":{"self":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/posts\/699","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/comments?post=699"}],"version-history":[{"count":0,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/posts\/699\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/media?parent=699"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/categories?post=699"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/tags?post=699"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}