{"id":44,"date":"2018-06-09T14:19:50","date_gmt":"2018-06-09T14:19:50","guid":{"rendered":"https:\/\/datablog.roman-halliday.com\/?p=44"},"modified":"2018-06-13T19:01:23","modified_gmt":"2018-06-13T19:01:23","slug":"dates-in-sql-server-iteration-of-date-ranges","status":"publish","type":"post","link":"https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/","title":{"rendered":"Dates In SQL Server: Iteration of Date Ranges"},"content":{"rendered":"<p>When performing ETL functions, it&#8217;s often required to run processes\u00a0with iteration over a given date range. Here are some examples of iterating over dates. These methods can also be applied to other cases where we want to do some iteration.<\/p>\n<p>After my previous posts\u00a0looking at dates, particularly\u00a0<a href=\"https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/01\/dates-in-sql-server-create-sample-date-ranges\/\">Dates In SQL Server: Create Sample Date Ranges<\/a>. I thought it worth looking at looping over dates. This is less about manipulating dates in tables, and more about targeted to methods for managing dates used in ETL processes. These examples use common iteration techniques, with an emphasis on dates.<\/p>\n<h1>Going round and round dates<\/h1>\n<p>There are a number of ways to create iteration within SQL Server, the two most common methods are loops, and cursors. For loops, I prefer to use a WHILE structure.<\/p>\n<h2>WHILE loop iterating dates<\/h2>\n<p>This is the most simple method, and familiar to people with a procedural background. The advantage is that it&#8217;s quicker and easier to create, the disadvantage is the opportunity for an infinite loop!<\/p>\n<p>Be careful:<\/p>\n<ol>\n<li>If you don&#8217;t do the increment correctly (at the end) you can create an infinite loop.<\/li>\n<li>If the end date provided is before the start date you can create an infinite loop. A\u00a0best practises implementation would check this before starting the loop.<\/li>\n<\/ol>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">DECLARE @DateStart DATE  = '01-JAN-2018';\r\nDECLARE @DateEnd DATE    = '01-FEB-2018';\r\nDECLARE @DateActive DATE = @DateStart;\r\n \t \t \r\nPRINT CONVERT(VARCHAR, GetDate(), 120) + ' - Started Date Range: ' + CONVERT(VARCHAR(20), @DateStart, 120) + ' -&gt; ' + CONVERT(VARCHAR(20), @DateEnd, 120);\r\n \t \t \r\nWHILE @DateActive &amp;lt;= @DateEnd\r\nBEGIN\r\n    PRINT CONVERT(VARCHAR, GetDate(), 120) + ' - Executing Day: ' + CONVERT(VARCHAR(20), @DateActive, 120);\r\n    ----------------------------------------------------------------------------\r\n    -- Process\r\n    ----------------------------------------------------------------------------\r\n    \/*\r\n    EXECUTE [DB].[Schema].[stored_procedure] @DateVariable = @DateActive;\r\n    *\/\r\n    \r\n    \/*\r\n    SELECT [DateField], COUNT(*) AS [count_rows]\r\n      FROM [DB].[Schema].[table \u201c\u201d not found \/]<br \/>\n\r\n     WHERE [DateField] = @DateActive\r\n    ;\r\n    *\/\r\n    \t \t \r\n    ----------------------------------------------------------------------------\r\n    -- Increment\r\n    ----------------------------------------------------------------------------\r\n    SET @DateActive = DateAdd(Day, 1, @DateActive);\r\nEND;\r\n \t \t \r\nPRINT CONVERT(VARCHAR, GetDate(), 120) + ' - Completed Date Range: ' + CONVERT(VARCHAR(20), @DateStart, 120) + ' -&gt; ' + CONVERT(VARCHAR(20), @DateEnd, 120);<\/pre>\n<p>&nbsp;<\/p>\n<h2>Cursor\u00a0iterating dates<\/h2>\n<p>When doing iteration in ETL processing this is the more common method, it prevents us from having infinite loops and allows us to iterate over any data type(s) easily including having more than one variable in the loop. The down side is it requires a little more code\/logic.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">--------------------------------------------------------------------------------\r\n-- Create Sample Data (process control table)\r\n--------------------------------------------------------------------------------\r\n\r\nCREATE TABLE #SampleData\r\n(\r\n    date_col       DATE NOT NULL PRIMARY KEY,\r\n    processed_date DATETIME2(2) -- Null is unprocessed\r\n);\r\n\r\nINSERT INTO #SampleData (date_col, processed_date) VALUES (GetDate() -3, GetDate() -1); -- Example of data already processed\r\nINSERT INTO #SampleData (date_col, processed_date) VALUES (GetDate() -2, NULL);\r\nINSERT INTO #SampleData (date_col, processed_date) VALUES (GetDate() -1, NULL);\r\n\r\n--------------------------------------------------------------------------------\r\n-- Craete Cursor\r\n--------------------------------------------------------------------------------\r\nDECLARE processing_date_cursor CURSOR FOR\r\nSELECT date_col\r\n  FROM #SampleData\r\n WHERE processed_date IS NULL\r\n;\r\n\r\n--------------------------------------------------------------------------------\r\n-- Iterate Cursor\r\n--------------------------------------------------------------------------------\r\nDECLARE @DateActive DATE;\r\n\r\nOPEN processing_date_cursor;\r\nFETCH NEXT FROM processing_date_cursor INTO @DateActive;\r\n\r\nIF @@FETCH_STATUS &lt;&gt; 0   \r\n    PRINT 'Empty Cursor'       \r\nWHILE @@FETCH_STATUS = 0  \r\nBEGIN\r\n    PRINT CONVERT(VARCHAR, GetDate(), 120) + ' - Executing Day: ' + CONVERT(VARCHAR(20), @DateActive, 120);\r\n    ----------------------------------------------------------------------------\r\n    -- Process Start\r\n    ----------------------------------------------------------------------------\r\n    \/*\r\n    EXECUTE [DB].[Schema].[stored_procedure] @DateVariable = @DateActive;\r\n    *\/\r\n    \r\n    ----------------------------------------------------------------------------\r\n    -- For this example, log to table\r\n    UPDATE #SampleData\r\n       SET processed_date = GetDate()\r\n     WHERE date_col = @DateActive\r\n    ;\r\n    \r\n    ----------------------------------------------------------------------------\r\n    -- Process End\r\n    ----------------------------------------------------------------------------\r\n    FETCH NEXT FROM processing_date_cursor INTO @DateActive;\r\nEND\r\n\r\nCLOSE processing_date_cursor;  \r\nDEALLOCATE processing_date_cursor;\r\n<\/pre>\n<p>See it in action over on\u00a0<a href=\"http:\/\/rextester.com\/LVSZCE52500\">rextester.com<\/a><\/p>\n<h1>Dynamic batches of dates<\/h1>\n<p>As I used this to process groups of dates previously, and I think it&#8217;s an interesting template to be able to copy\/paste from I&#8217;ll include it here.<\/p>\n<p>In my scenario, I had a large amount of history to reprocess. Doing the whole dataset was too much for a single transaction (it locked one table for too long), however day by day was also inefficient. I wanted to do windows of processing, but needed to experiment on the size of the date range in each batch. So I created the below:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">--------------------------------------------------------------------------------\r\n-- Define begin\/end dates and batch size\r\n--------------------------------------------------------------------------------\r\nDECLARE @DateStart  DATE = '01-JAN-18';\r\nDECLARE @DateEnd    DATE = '01-FEB-18';\r\nDECLARE @BatchSize  INT  = 5;\r\n\r\nPRINT CONVERT(VARCHAR, GetDate(), 120) + ' - Started Date Range: ' + CONVERT(VARCHAR(20), @DateStart, 120) + ' -&gt; '  + CONVERT(VARCHAR(20), @DateEnd, 120);\r\n\r\n--------------------------------------------------------------------------------\r\n-- Create batch variables and populate with first values\r\n--------------------------------------------------------------------------------\r\nDECLARE @DateActiveStart DATE = @DateStart;\r\nDECLARE @FutureDate      DATE = DateAdd(DAY, @BatchSize - 1, @DateActiveStart); -- Note: subtract 1 from @BatchSize as we include the start date in the batch\r\nDECLARE @DateActiveEnd   DATE = CASE WHEN @FutureDate &lt; @DateEnd THEN @FutureDate ELSE @DateEnd END;\r\n\r\nWHILE @DateActiveStart &lt;= @DateEnd\r\nBEGIN\r\n    PRINT CONVERT(VARCHAR, GetDate(), 120) + ' - Executing Batch: ' + CONVERT(VARCHAR(20), @DateActiveStart, 120) + ' -&gt; '  + CONVERT(VARCHAR(20), @DateActiveEnd, 120);\r\n    ----------------------------------------------------------------------------\r\n    -- Process\r\n    ----------------------------------------------------------------------------\r\n  --SELECT CONVERT(VARCHAR, GetDate(), 120) + ' - Executing Batch: ' + CONVERT(VARCHAR(20), @DateActiveStart, 120) + ' -&gt; '  + CONVERT(VARCHAR(20), @DateActiveEnd, 120) AS [output];\r\n    \/*\r\n    EXECUTE [DB].[Schema].[stored_procedure] @DateVariable1 = @DateActiveStart, @DateVariable2 = @DateActiveEnd, ;\r\n    *\/\r\n \r\n    ----------------------------------------------------------------------------\r\n    -- Increment\r\n    ----------------------------------------------------------------------------\r\n    SET @DateActiveStart = DateAdd(Day, 1, @DateActiveEnd);\r\n    SET @FutureDate      = DateAdd(DAY, @BatchSize - 1, @DateActiveStart); -- Note: subtract 1 from @BatchSize as we include the start date in the batch\r\n    SET @DateActiveEnd   = CASE WHEN @FutureDate &lt; @DateEnd THEN @FutureDate ELSE @DateEnd END;\r\nEND;\r\n \r\nPRINT CONVERT(VARCHAR, GetDate(), 120) + ' - Completed Date Range: ' + CONVERT(VARCHAR(20), @DateStart, 120) + ' -&gt; '  + CONVERT(VARCHAR(20), @DateEnd, 120);<\/pre>\n<p>See it in action over at\u00a0<a href=\"http:\/\/rextester.com\/SKN54241\">http:\/\/rextester.com<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>When performing ETL functions, it&#8217;s often required to run processes\u00a0with iteration over a given date range. Here are some examples of iterating over dates. These methods can also be applied to other cases where we want to do some iteration. After my previous posts\u00a0looking at dates, particularly\u00a0Dates In SQL Server: Create Sample Date Ranges. I&hellip;<\/p>\n<p class=\"read-more\"><a class=\"readmore-btn\" href=\"https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/\">Read More<span class=\"screen-reader-text\">  Read More<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,4],"tags":[12],"class_list":["post-44","post","type-post","status-publish","format-standard","hentry","category-databases","category-sql-server","tag-date"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Dates In SQL Server: Iteration of Date Ranges - Rows Across The Lake<\/title>\n<meta name=\"description\" content=\"When performing ETL functions, it&#039;s often required to run processes\u00a0with iteration over a given date range. Here are some examples of iterating over dates.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Dates In SQL Server: Iteration of Date Ranges - Rows Across The Lake\" \/>\n<meta property=\"og:description\" content=\"When performing ETL functions, it&#039;s often required to run processes\u00a0with iteration over a given date range. Here are some examples of iterating over dates.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/\" \/>\n<meta property=\"og:site_name\" content=\"Rows Across The Lake\" \/>\n<meta property=\"article:published_time\" content=\"2018-06-09T14:19:50+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-06-13T19:01:23+00:00\" \/>\n<meta name=\"author\" content=\"david\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@d_roman_h\" \/>\n<meta name=\"twitter:site\" content=\"@d_roman_h\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"david\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/index.php\\\/2018\\\/06\\\/09\\\/dates-in-sql-server-iteration-of-date-ranges\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/index.php\\\/2018\\\/06\\\/09\\\/dates-in-sql-server-iteration-of-date-ranges\\\/\"},\"author\":{\"name\":\"david\",\"@id\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/#\\\/schema\\\/person\\\/575f96d2590c3085923ff9e1b565748b\"},\"headline\":\"Dates In SQL Server: Iteration of Date Ranges\",\"datePublished\":\"2018-06-09T14:19:50+00:00\",\"dateModified\":\"2018-06-13T19:01:23+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/index.php\\\/2018\\\/06\\\/09\\\/dates-in-sql-server-iteration-of-date-ranges\\\/\"},\"wordCount\":394,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/#\\\/schema\\\/person\\\/575f96d2590c3085923ff9e1b565748b\"},\"keywords\":[\"date\"],\"articleSection\":[\"Databases\",\"SQL Server\"],\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/datablog.roman-halliday.com\\\/index.php\\\/2018\\\/06\\\/09\\\/dates-in-sql-server-iteration-of-date-ranges\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/index.php\\\/2018\\\/06\\\/09\\\/dates-in-sql-server-iteration-of-date-ranges\\\/\",\"url\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/index.php\\\/2018\\\/06\\\/09\\\/dates-in-sql-server-iteration-of-date-ranges\\\/\",\"name\":\"Dates In SQL Server: Iteration of Date Ranges - Rows Across The Lake\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/#website\"},\"datePublished\":\"2018-06-09T14:19:50+00:00\",\"dateModified\":\"2018-06-13T19:01:23+00:00\",\"description\":\"When performing ETL functions, it's often required to run processes\u00a0with iteration over a given date range. Here are some examples of iterating over dates.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/index.php\\\/2018\\\/06\\\/09\\\/dates-in-sql-server-iteration-of-date-ranges\\\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/datablog.roman-halliday.com\\\/index.php\\\/2018\\\/06\\\/09\\\/dates-in-sql-server-iteration-of-date-ranges\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/index.php\\\/2018\\\/06\\\/09\\\/dates-in-sql-server-iteration-of-date-ranges\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Dates In SQL Server: Iteration of Date Ranges\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/#website\",\"url\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/\",\"name\":\"Rows Across The Lake\",\"description\":\"Data &amp; Databases\",\"publisher\":{\"@id\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/#\\\/schema\\\/person\\\/575f96d2590c3085923ff9e1b565748b\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/datablog.roman-halliday.com\\\/#\\\/schema\\\/person\\\/575f96d2590c3085923ff9e1b565748b\",\"name\":\"david\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/acddbc676a1d5c73795edcf0627ee39e5aa947da9033b58373e03d93122cb3b7?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/acddbc676a1d5c73795edcf0627ee39e5aa947da9033b58373e03d93122cb3b7?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/acddbc676a1d5c73795edcf0627ee39e5aa947da9033b58373e03d93122cb3b7?s=96&d=mm&r=g\",\"caption\":\"david\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/acddbc676a1d5c73795edcf0627ee39e5aa947da9033b58373e03d93122cb3b7?s=96&d=mm&r=g\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Dates In SQL Server: Iteration of Date Ranges - Rows Across The Lake","description":"When performing ETL functions, it's often required to run processes\u00a0with iteration over a given date range. Here are some examples of iterating over dates.","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:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/","og_locale":"en_GB","og_type":"article","og_title":"Dates In SQL Server: Iteration of Date Ranges - Rows Across The Lake","og_description":"When performing ETL functions, it's often required to run processes\u00a0with iteration over a given date range. Here are some examples of iterating over dates.","og_url":"https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/","og_site_name":"Rows Across The Lake","article_published_time":"2018-06-09T14:19:50+00:00","article_modified_time":"2018-06-13T19:01:23+00:00","author":"david","twitter_card":"summary_large_image","twitter_creator":"@d_roman_h","twitter_site":"@d_roman_h","twitter_misc":{"Written by":"david","Estimated reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/#article","isPartOf":{"@id":"https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/"},"author":{"name":"david","@id":"https:\/\/datablog.roman-halliday.com\/#\/schema\/person\/575f96d2590c3085923ff9e1b565748b"},"headline":"Dates In SQL Server: Iteration of Date Ranges","datePublished":"2018-06-09T14:19:50+00:00","dateModified":"2018-06-13T19:01:23+00:00","mainEntityOfPage":{"@id":"https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/"},"wordCount":394,"commentCount":0,"publisher":{"@id":"https:\/\/datablog.roman-halliday.com\/#\/schema\/person\/575f96d2590c3085923ff9e1b565748b"},"keywords":["date"],"articleSection":["Databases","SQL Server"],"inLanguage":"en-GB","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/","url":"https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/","name":"Dates In SQL Server: Iteration of Date Ranges - Rows Across The Lake","isPartOf":{"@id":"https:\/\/datablog.roman-halliday.com\/#website"},"datePublished":"2018-06-09T14:19:50+00:00","dateModified":"2018-06-13T19:01:23+00:00","description":"When performing ETL functions, it's often required to run processes\u00a0with iteration over a given date range. Here are some examples of iterating over dates.","breadcrumb":{"@id":"https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/datablog.roman-halliday.com\/index.php\/2018\/06\/09\/dates-in-sql-server-iteration-of-date-ranges\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/datablog.roman-halliday.com\/"},{"@type":"ListItem","position":2,"name":"Dates In SQL Server: Iteration of Date Ranges"}]},{"@type":"WebSite","@id":"https:\/\/datablog.roman-halliday.com\/#website","url":"https:\/\/datablog.roman-halliday.com\/","name":"Rows Across The Lake","description":"Data &amp; Databases","publisher":{"@id":"https:\/\/datablog.roman-halliday.com\/#\/schema\/person\/575f96d2590c3085923ff9e1b565748b"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/datablog.roman-halliday.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":["Person","Organization"],"@id":"https:\/\/datablog.roman-halliday.com\/#\/schema\/person\/575f96d2590c3085923ff9e1b565748b","name":"david","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/secure.gravatar.com\/avatar\/acddbc676a1d5c73795edcf0627ee39e5aa947da9033b58373e03d93122cb3b7?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/acddbc676a1d5c73795edcf0627ee39e5aa947da9033b58373e03d93122cb3b7?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/acddbc676a1d5c73795edcf0627ee39e5aa947da9033b58373e03d93122cb3b7?s=96&d=mm&r=g","caption":"david"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/acddbc676a1d5c73795edcf0627ee39e5aa947da9033b58373e03d93122cb3b7?s=96&d=mm&r=g"}}]}},"_links":{"self":[{"href":"https:\/\/datablog.roman-halliday.com\/index.php\/wp-json\/wp\/v2\/posts\/44","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/datablog.roman-halliday.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/datablog.roman-halliday.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/datablog.roman-halliday.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/datablog.roman-halliday.com\/index.php\/wp-json\/wp\/v2\/comments?post=44"}],"version-history":[{"count":11,"href":"https:\/\/datablog.roman-halliday.com\/index.php\/wp-json\/wp\/v2\/posts\/44\/revisions"}],"predecessor-version":[{"id":134,"href":"https:\/\/datablog.roman-halliday.com\/index.php\/wp-json\/wp\/v2\/posts\/44\/revisions\/134"}],"wp:attachment":[{"href":"https:\/\/datablog.roman-halliday.com\/index.php\/wp-json\/wp\/v2\/media?parent=44"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/datablog.roman-halliday.com\/index.php\/wp-json\/wp\/v2\/categories?post=44"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/datablog.roman-halliday.com\/index.php\/wp-json\/wp\/v2\/tags?post=44"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}