{"id":3214,"date":"2016-03-05T16:53:56","date_gmt":"2016-03-05T16:53:56","guid":{"rendered":"http:\/\/www.garysieling.com\/blog\/?p=3214"},"modified":"2016-03-05T16:53:56","modified_gmt":"2016-03-05T16:53:56","slug":"accessing-values-in-anonymous-row-types-in-postgres","status":"publish","type":"post","link":"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/","title":{"rendered":"Accessing values in anonymous row types in Postgres"},"content":{"rendered":"<p>If you are trying to build pivot tables in Postgres, you may find examples online that incorrectly push you towards using the &#8220;ROW&#8221; type to build the pivot table. You might try something like the following (which will not work):<\/p>\n<pre lang=sql\">\ncreate type event_counts as (event_type_1, event_type_2);\n\nselect \n  user,\n  event_count[0].event_type1,\n  event_count[0].event_type2\nfrom (\n  select \n    user, \n    array_agg(ROW(events)::event_counts order by event_type ASC) event_count\n  from ( \n    select user, event_type, count(*) events\n    from (\n      select 'Event type 1' event_type, 'gsieling' as user\n      union all\n      select 'Event type 2' event_type, 'gsieling' as user\n      union all \n      select 'Event type 1' event_type, 'otheruser' as user\n    ) b\n    group by 1, 2\n  ) a\n<\/pre>\n<p>Unfortunately, the above example won&#8217;t actually work &#8211; you can&#8217;t cast the row to event_counts in this case (tested in 9.3). If you use an anonymous row type, it won&#8217;t work at all (there seems to be no way to get the contents).  There are many confused stackoverflow posts on the subject, with the people providing &#8220;answers&#8221; blaming the asker.<\/p>\n<p>The correct way to fix this is to switch to using an array and skip the row type entirely, which you can access by index:<\/p>\n<pre lang=\"sql\">\nselect \n  user,\n  event_count[1] event_1,\n  event_count[2] event_2\nfrom (\n  select \n    user, \n    array_agg(events order by event_type ASC) event_count\n  from ( \n    select user, event_type, count(*) events from (\n      select 'Event type 1' event_type, 'gsieling' as user\n      union all\n      select 'Event type 2' event_type, 'gsieling' as user\n      union all \n      select 'Event type 1' event_type, 'otheruser' as user\n    ) b\n    group by 1, 2\n  ) a\n) c\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>If you are trying to build pivot tables in Postgres, you may find examples online that incorrectly push you towards using the &#8220;ROW&#8221; type to build the pivot table. You might try something like the following (which will not work):<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"footnotes":""},"categories":[4],"tags":[435,437,461,523],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.9 - aioseo.com -->\n\t<meta name=\"description\" content=\"If you are trying to build pivot tables in Postgres, you may find examples online that incorrectly push you towards using the &quot;ROW&quot; type to build the pivot table. You might try something like the following (which will not work):\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"gary\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.9\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Gary Sieling - Software Engineer\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Accessing values in anonymous row types in Postgres - Gary Sieling\" \/>\n\t\t<meta property=\"og:description\" content=\"If you are trying to build pivot tables in Postgres, you may find examples online that incorrectly push you towards using the &quot;ROW&quot; type to build the pivot table. You might try something like the following (which will not work):\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2016-03-05T16:53:56+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2016-03-05T16:53:56+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Accessing values in anonymous row types in Postgres - Gary Sieling\" \/>\n\t\t<meta name=\"twitter:description\" content=\"If you are trying to build pivot tables in Postgres, you may find examples online that incorrectly push you towards using the &quot;ROW&quot; type to build the pivot table. You might try something like the following (which will not work):\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BlogPosting\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/accessing-values-in-anonymous-row-types-in-postgres\\\/#blogposting\",\"name\":\"Accessing values in anonymous row types in Postgres - Gary Sieling\",\"headline\":\"Accessing values in anonymous row types in Postgres\",\"author\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/author\\\/gary\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/#organization\"},\"datePublished\":\"2016-03-05T16:53:56+00:00\",\"dateModified\":\"2016-03-05T16:53:56+00:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/accessing-values-in-anonymous-row-types-in-postgres\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/accessing-values-in-anonymous-row-types-in-postgres\\\/#webpage\"},\"articleSection\":\"Code Examples, pivot table, postgres, reporting, sql\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/accessing-values-in-anonymous-row-types-in-postgres\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.garysieling.com\\\/blog\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/category\\\/code-examples\\\/#listItem\",\"name\":\"Code Examples\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/category\\\/code-examples\\\/#listItem\",\"position\":2,\"name\":\"Code Examples\",\"item\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/category\\\/code-examples\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/accessing-values-in-anonymous-row-types-in-postgres\\\/#listItem\",\"name\":\"Accessing values in anonymous row types in Postgres\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/accessing-values-in-anonymous-row-types-in-postgres\\\/#listItem\",\"position\":3,\"name\":\"Accessing values in anonymous row types in Postgres\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/category\\\/code-examples\\\/#listItem\",\"name\":\"Code Examples\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/#organization\",\"name\":\"Gary Sieling\",\"description\":\"Software Engineer\",\"url\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/author\\\/gary\\\/#author\",\"url\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/author\\\/gary\\\/\",\"name\":\"gary\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/accessing-values-in-anonymous-row-types-in-postgres\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/0be925276d848ffe98a6a9dc8cf33e67?s=96&d=identicon&r=g\",\"width\":96,\"height\":96,\"caption\":\"gary\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/accessing-values-in-anonymous-row-types-in-postgres\\\/#webpage\",\"url\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/accessing-values-in-anonymous-row-types-in-postgres\\\/\",\"name\":\"Accessing values in anonymous row types in Postgres - Gary Sieling\",\"description\":\"If you are trying to build pivot tables in Postgres, you may find examples online that incorrectly push you towards using the \\\"ROW\\\" type to build the pivot table. You might try something like the following (which will not work):\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/accessing-values-in-anonymous-row-types-in-postgres\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/author\\\/gary\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/author\\\/gary\\\/#author\"},\"datePublished\":\"2016-03-05T16:53:56+00:00\",\"dateModified\":\"2016-03-05T16:53:56+00:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/\",\"name\":\"Gary Sieling\",\"description\":\"Software Engineer\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Accessing values in anonymous row types in Postgres - Gary Sieling","description":"If you are trying to build pivot tables in Postgres, you may find examples online that incorrectly push you towards using the \"ROW\" type to build the pivot table. You might try something like the following (which will not work):","canonical_url":"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BlogPosting","@id":"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/#blogposting","name":"Accessing values in anonymous row types in Postgres - Gary Sieling","headline":"Accessing values in anonymous row types in Postgres","author":{"@id":"https:\/\/www.garysieling.com\/blog\/author\/gary\/#author"},"publisher":{"@id":"https:\/\/www.garysieling.com\/blog\/#organization"},"datePublished":"2016-03-05T16:53:56+00:00","dateModified":"2016-03-05T16:53:56+00:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/#webpage"},"isPartOf":{"@id":"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/#webpage"},"articleSection":"Code Examples, pivot table, postgres, reporting, sql"},{"@type":"BreadcrumbList","@id":"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.garysieling.com\/blog#listItem","position":1,"name":"Home","item":"https:\/\/www.garysieling.com\/blog","nextItem":{"@type":"ListItem","@id":"https:\/\/www.garysieling.com\/blog\/category\/code-examples\/#listItem","name":"Code Examples"}},{"@type":"ListItem","@id":"https:\/\/www.garysieling.com\/blog\/category\/code-examples\/#listItem","position":2,"name":"Code Examples","item":"https:\/\/www.garysieling.com\/blog\/category\/code-examples\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/#listItem","name":"Accessing values in anonymous row types in Postgres"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.garysieling.com\/blog#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/#listItem","position":3,"name":"Accessing values in anonymous row types in Postgres","previousItem":{"@type":"ListItem","@id":"https:\/\/www.garysieling.com\/blog\/category\/code-examples\/#listItem","name":"Code Examples"}}]},{"@type":"Organization","@id":"https:\/\/www.garysieling.com\/blog\/#organization","name":"Gary Sieling","description":"Software Engineer","url":"https:\/\/www.garysieling.com\/blog\/"},{"@type":"Person","@id":"https:\/\/www.garysieling.com\/blog\/author\/gary\/#author","url":"https:\/\/www.garysieling.com\/blog\/author\/gary\/","name":"gary","image":{"@type":"ImageObject","@id":"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/0be925276d848ffe98a6a9dc8cf33e67?s=96&d=identicon&r=g","width":96,"height":96,"caption":"gary"}},{"@type":"WebPage","@id":"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/#webpage","url":"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/","name":"Accessing values in anonymous row types in Postgres - Gary Sieling","description":"If you are trying to build pivot tables in Postgres, you may find examples online that incorrectly push you towards using the \"ROW\" type to build the pivot table. You might try something like the following (which will not work):","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/www.garysieling.com\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/#breadcrumblist"},"author":{"@id":"https:\/\/www.garysieling.com\/blog\/author\/gary\/#author"},"creator":{"@id":"https:\/\/www.garysieling.com\/blog\/author\/gary\/#author"},"datePublished":"2016-03-05T16:53:56+00:00","dateModified":"2016-03-05T16:53:56+00:00"},{"@type":"WebSite","@id":"https:\/\/www.garysieling.com\/blog\/#website","url":"https:\/\/www.garysieling.com\/blog\/","name":"Gary Sieling","description":"Software Engineer","inLanguage":"en-US","publisher":{"@id":"https:\/\/www.garysieling.com\/blog\/#organization"}}]},"og:locale":"en_US","og:site_name":"Gary Sieling - Software Engineer","og:type":"article","og:title":"Accessing values in anonymous row types in Postgres - Gary Sieling","og:description":"If you are trying to build pivot tables in Postgres, you may find examples online that incorrectly push you towards using the &quot;ROW&quot; type to build the pivot table. You might try something like the following (which will not work):","og:url":"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/","article:published_time":"2016-03-05T16:53:56+00:00","article:modified_time":"2016-03-05T16:53:56+00:00","twitter:card":"summary_large_image","twitter:title":"Accessing values in anonymous row types in Postgres - Gary Sieling","twitter:description":"If you are trying to build pivot tables in Postgres, you may find examples online that incorrectly push you towards using the &quot;ROW&quot; type to build the pivot table. You might try something like the following (which will not work):"},"aioseo_meta_data":{"post_id":"3214","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"limit_modified_date":false,"created":"2023-02-04 16:39:53","updated":"2026-07-06 01:32:07","ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.garysieling.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.garysieling.com\/blog\/category\/code-examples\/\" title=\"Code Examples\">Code Examples<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tAccessing values in anonymous row types in Postgres\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.garysieling.com\/blog"},{"label":"Code Examples","link":"https:\/\/www.garysieling.com\/blog\/category\/code-examples\/"},{"label":"Accessing values in anonymous row types in Postgres","link":"https:\/\/www.garysieling.com\/blog\/accessing-values-in-anonymous-row-types-in-postgres\/"}],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/posts\/3214"}],"collection":[{"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/comments?post=3214"}],"version-history":[{"count":0,"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/posts\/3214\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/media?parent=3214"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/categories?post=3214"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/tags?post=3214"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}