<?xml version="1.0" encoding="UTF-8" ?><!-- generator=Zoho Sites --><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><atom:link href="https://www.prescient.consulting/blogs/author/kpauligk/feed" rel="self" type="application/rss+xml"/><title>Prescient Analytics - Blog by kpauligk</title><description>Prescient Analytics - Blog by kpauligk</description><link>https://www.prescient.consulting/blogs/author/kpauligk</link><lastBuildDate>Fri, 12 Sep 2025 06:45:52 -0700</lastBuildDate><generator>http://zoho.com/sites/</generator><item><title><![CDATA[Handling "Valid" SQL Join Duplication]]></title><link>https://www.prescient.consulting/blogs/post/Handling-Valid-SQL-Join-Duplication</link><description><![CDATA[A method of removing rows resulting from valid join duplication]]></description><content:encoded><![CDATA[<div class="zpcontent-container blogpost-container "><div data-element-id="elm_4k4FPTQDSgS8BV9_lofMlA" data-element-type="section" class="zpsection "><style type="text/css"></style><div class="zpcontainer-fluid zpcontainer"><div data-element-id="elm_f7Dwrx1AT_mxpu1hWLKezQ" data-element-type="row" class="zprow zprow-container zpalign-items- zpjustify-content- " data-equal-column=""><style type="text/css"></style><div data-element-id="elm_RHNSRo9qQ7yQLMdAc-rJlA" data-element-type="column" class="zpelem-col zpcol-12 zpcol-md-12 zpcol-sm-12 zpalign-self- "><style type="text/css"></style><div data-element-id="elm_l1gLovDeSu6aeKGjds8mBA" data-element-type="text" class="zpelement zpelem-text "><style> [data-element-id="elm_l1gLovDeSu6aeKGjds8mBA"].zpelem-text { border-radius:1px; } </style><div class="zptext zptext-align-center " data-editor="true"><p style="text-align:left;">A hump that most people starting out in SQL have to get over is how joins work - that is, thinking relational.</p><div style="text-align:left;">A scenario that came up recently involved matching payments in two different systems, the purpose of which was to trace it back to a source vendor.&nbsp;</div><p style="text-align:left;"><span style="color:inherit;"><br></span></p><div style="text-align:left;">An issue I experienced was the case of “valid” duplicate joining – that is there were two transactions in one table and two in the other and both had the same join column values. Therefore the result with relational joining is that four records are returned since they all join to each other, rather than the desired two.</div><p style="text-align:left;"><span style="color:inherit;"><br></span></p><div style="text-align:left;">One way to remove these duplicates is to use good old row_number() to generate a pseudo-key to filter them out.</div><p style="text-align:left;"><span style="color:inherit;"><br></span></p><div style="text-align:left;">This is somewhat arbitrary depending on the data, since the only control you have is in the order by clause of the row_number() function. In my use case this was acceptable since other key conditions were met in the join clause.</div><div style="text-align:left;"><br></div><div style="text-align:left;">Below is an example demonstrating this approach:</div></div>
</div><div data-element-id="elm_bExIWV-58ES3vCCUX0su9g" data-element-type="text" class="zpelement zpelem-text code-block "><style> [data-element-id="elm_bExIWV-58ES3vCCUX0su9g"].zpelem-text { border-radius:1px; } </style><div class="zptext zptext-align-left " data-editor="true"><p><span style="color:inherit;"></span></p><div>create temporary table test_legit_matches_1 (</div><p>&nbsp; &nbsp; idx1 int,<br></p><p>&nbsp; &nbsp; col1 text,<br></p><p>&nbsp; &nbsp; join_col text<br></p><p>);<br></p><p><span style="color:inherit;"><br></span></p><div>create temporary table test_legit_matches_2 (</div><p>&nbsp; &nbsp; idx2 int,<br></p><p>&nbsp; &nbsp; col2 text,<br></p><p>&nbsp; &nbsp; join_col text<br></p><p>);<br></p><p><br></p><div>insert into test_legit_matches_1 values (1, 'val1', 'join me');</div><p>insert into test_legit_matches_1 values (2, 'val2', 'join me');<br></p><p>insert into test_legit_matches_1 values (3, 'val3', 'nice join');<br></p><p>insert into test_legit_matches_2 values (1, 'val4', 'join me');<br></p><p>insert into test_legit_matches_2 values (2, 'val5', 'join me');<br></p><p>insert into test_legit_matches_2 values (3, 'val6', 'nice join');<br></p><p><br></p><div>-- observed duplication</div><p>select<br></p><p>&nbsp; &nbsp; *<br></p><p>from test_legit_matches_1 as t1<br></p><p><br></p><div>left outer join test_legit_matches_2 as t2</div><p>on t1.join_col = t2.join_col<br></p><p>;<br></p><p><span style="color:inherit;"><br></span></p><div>-- duplication removed, though join is potentially arbitrary (based on order by clauses)<br></div><p>with _joined as (<br></p><p>&nbsp; &nbsp; select<br></p><p>&nbsp; &nbsp; &nbsp; &nbsp; *<br></p><p>&nbsp; &nbsp; &nbsp; &nbsp; , row_number() over (partition by idx1 order by idx2) as idx1_rn<br></p><p>&nbsp; &nbsp; &nbsp; &nbsp; , row_number() over (partition by idx2 order by idx1) as idx2_rn<br></p><p><br></p><p>&nbsp; &nbsp; from test_legit_matches_1 as t1<br></p><p><br></p><div>&nbsp; &nbsp; left outer join test_legit_matches_2 as t2</div><p>&nbsp; &nbsp; on t1.join_col = t2.join_col<br></p><p><span style="color:inherit;"><br></span></p><div>)</div><p><span style="color:inherit;"><br></span></p><div>select *</div><p>from _joined<br></p><p>where idx1_rn = idx2_rn</p><div>;</div></div>
</div><div data-element-id="elm_wrZJrxgLI0R9aM2P0j1a4w" data-element-type="text" class="zpelement zpelem-text "><style> [data-element-id="elm_wrZJrxgLI0R9aM2P0j1a4w"].zpelem-text { border-radius:1px; } </style><div class="zptext zptext-align-left " data-editor="true"><p>Result 1:</p><p><img src="/files/dups_result1.PNG"><br></p><p>Result 2:</p><p><img src="/files/dups_result2.PNG"><br></p></div>
</div></div></div></div></div></div> ]]></content:encoded><pubDate>Fri, 06 Dec 2019 12:45:10 +1030</pubDate></item><item><title><![CDATA[The type initializer for 'Amazon.Runtime.Internal.Settings.PersistenceManager' threw an exception]]></title><link>https://www.prescient.consulting/blogs/post/aws-type-initializer-exception</link><description><![CDATA[How to fix The type initializer for 'Amazon.Runtime.Internal.Settings.PersistenceManager' threw an exception]]></description><content:encoded><![CDATA[<div class="zpcontent-container blogpost-container "><div data-element-id="elm_85OUWBxYTv6-moHrQPSQDA" data-element-type="section" class="zpsection "><style type="text/css"></style><div class="zpcontainer-fluid zpcontainer"><div data-element-id="elm_e1zAgyHFT_ypNwrAe9YRYA" data-element-type="row" class="zprow zprow-container zpalign-items- zpjustify-content- " data-equal-column=""><style type="text/css"></style><div data-element-id="elm_c2ZKmhKEQ8SSrO2IRI6jZg" data-element-type="column" class="zpelem-col zpcol-12 zpcol-md-12 zpcol-sm-12 zpalign-self- "><style type="text/css"></style><div data-element-id="elm_M9NxART0QWuje111M8rIwQ" data-element-type="text" class="zpelement zpelem-text "><style> [data-element-id="elm_M9NxART0QWuje111M8rIwQ"].zpelem-text { border-radius:1px; } </style><div class="zptext zptext-align-center " data-editor="true"><p style="text-align:left;">I was faced with this lovely error message from a process that had been running successfully for some time.</p><p style="text-align:left;"><br></p><p style="text-align:left;">It was a Powershell script running in an Azure Function App, and my initial internet research did not reveal many clues as to why this would be case.</p><p style="text-align:left;"><br></p><p style="text-align:left;">On a hunch, I thought to update the AWS Powershell modules it was using - though they were not particularly old, I figured it couldn't hurt. So I did exactly that and voila, I tested the process and we were back in business.... for a few days least.</p><p style="text-align:left;"><br></p><p style="text-align:left;">The exception was back.</p><p style="text-align:left;"><br></p><p style="text-align:left;">I stumbled on a clue whilst reading a stack overflow response pointing at the parameters of an AWS function the OP was having trouble with. Following this, I double checked the parameters of the function that was failing (<span style="color:inherit;">Get-S3Object) and found I hadn't set the Region parameter. I added the parameter, tested it and no exception! This looks to have been the root cause, though why it worked up to that point is a bit of a mystery to me. A</span><span style="color:inherit;text-align:center;">s an aside, I have not had this issue ever in my local environment (in Powershell ISE).</span></p><p style="text-align:left;"><span style="color:inherit;"><br></span></p><p style="text-align:left;"><span style="color:inherit;">Perhaps it should be made a required parameter given the potential exception it may raise though.</span></p><p style="text-align:left;"><span style="color:inherit;"><br></span></p><p style="text-align:left;">I hope this helps someone, because it was pretty obscure...to me at least!</p></div>
</div></div></div></div></div></div> ]]></content:encoded><pubDate>Thu, 01 Aug 2019 22:31:02 +0930</pubDate></item><item><title><![CDATA[Data Analytics Project Blueprint]]></title><link>https://www.prescient.consulting/blogs/post/analytics-blueprint</link><description><![CDATA[A blueprint to assist in approaching a data analytics initiative in an organisation.]]></description><content:encoded><![CDATA[<div class="zpcontent-container blogpost-container "><div data-element-id="elm_pYnrzL6bTLyYAmo6n9t3RQ" data-element-type="section" class="zpsection "><style type="text/css"></style><div class="zpcontainer-fluid zpcontainer"><div data-element-id="elm_AWTG9Tk_S3OsqXs60nO25A" data-element-type="row" class="zprow zprow-container zpalign-items- zpjustify-content- " data-equal-column=""><style type="text/css"></style><div data-element-id="elm_cMNgOyBtSFyvHu9-mSxduQ" data-element-type="column" class="zpelem-col zpcol-12 zpcol-md-12 zpcol-sm-12 zpalign-self- "><style type="text/css"></style><div data-element-id="elm_ZYewbNcGQw6X-dZ84DdxUw" data-element-type="text" class="zpelement zpelem-text "><style> [data-element-id="elm_ZYewbNcGQw6X-dZ84DdxUw"].zpelem-text { border-style:none; } </style><div class="zptext zptext-align-center " data-editor="true"><p style="text-align:justify;">We recently had the opportunity to put some of our experience to paper in order to assist a client who is seeking to implement organisational analytics in a meaningful way for the first time.</p><p style="text-align:justify;"><br></p><p style="text-align:justify;">The attached image is the high level 'blueprint' put together that we believe encompasses the main activities that need to be undertaken to be ultimately successful in execution. Naturally behind each is a lot more detail on specifics of the activity, the outputs generated and the relationship with other activities.</p><p style="text-align:justify;"><br></p><p style="text-align:justify;">Important to note though is that this does not override project management activities, merely complements it with specific items that relate to data and analytics projects. I.E. it specifically does not refer to activities like risk management, budget management, communications plans etc.</p><p style="text-align:justify;"><br></p></div>
</div><div data-element-id="elm_b5F8m_B9Hzqxp33cEL739g" data-element-type="image" class="zpelement zpelem-image "><style> [data-element-id="elm_b5F8m_B9Hzqxp33cEL739g"] .zpimage-container figure figcaption .zpimage-caption-content { text-transform:none; } [data-element-id="elm_b5F8m_B9Hzqxp33cEL739g"].zpelem-image { border-style:none; border-radius:1px; box-shadow:0px 0px 0px 0px #000000; } </style><div data-caption-color="" data-size-tablet="" data-size-mobile="" data-align="center" data-tablet-image-separate="" data-mobile-image-separate="" class="zpimage-container zpimage-align-center zpimage-size-fit zpimage-tablet-fallback-fit zpimage-mobile-fallback-fit hb-lightbox " data-lightbox-options="
                type:fullscreen,
                theme:dark"><figure role="none" class="zpimage-data-ref"><span class="zpimage-anchor" role="link" tabindex="0" aria-label="Open Lightbox" style="cursor:pointer;"><picture><img class="zpimage zpimage-style-none zpimage-space-none " src="/files/Project%20Blueprint%20Overview.png" size="fit" data-lightbox="true" style="width:100%;padding:0px;margin:0px;"/></picture></span></figure></div>
</div></div></div></div></div></div> ]]></content:encoded><pubDate>Thu, 02 May 2019 10:18:57 +0930</pubDate></item><item><title><![CDATA[First Look at OR-Tools]]></title><link>https://www.prescient.consulting/blogs/post/First-Look-OR-Tools</link><description><![CDATA[<img align="left" hspace="5" src="https://www.prescient.consulting/files/blog_img/orLogo-1-.png"/>First look at using Google's Open Source OR-Tools library for Constraint Optimsation.]]></description><content:encoded><![CDATA[<div class="zpcontent-container blogpost-container "><div data-element-id="elm_I97l1t8iQ72z75_r7crdyw" data-element-type="section" class="zpsection "><style type="text/css"></style><div class="zpcontainer-fluid zpcontainer"><div data-element-id="elm_5PJA_zveQA6M5sESoehAqg" data-element-type="row" class="zprow zprow-container zpalign-items- zpjustify-content- " data-equal-column=""><style type="text/css"></style><div data-element-id="elm_6Md-l1NRT7eZPKEVJF2Oog" data-element-type="column" class="zpelem-col zpcol-12 zpcol-md-12 zpcol-sm-12 zpalign-self- "><style type="text/css"></style><div data-element-id="elm_H7WQoc21QPK6jvTiH8AKLA" data-element-type="text" class="zpelement zpelem-text "><style></style><div class="zptext zptext-align-center " data-editor="true"><div style="text-align:left;"><div>For a recent project that involved an optimisation problem, I settled on using the OR-Tools library, an open-source project from Google (<a href="https://developers.google.com/optimization" title="https://developers.google.com/optimization" target="_blank">https://developers.google.com/optimization</a>).</div></div><div style="text-align:left;"><div><br></div><div>Of interest to me was its CP-SAT solver which claimed good solution speed based on Constraint Programming (<a href="https://en.wikipedia.org/wiki/Constraint_programming" title="https://en.wikipedia.org/wiki/Constraint_programming" target="_blank">https://en.wikipedia.org/wiki/Constraint_programming</a>)</div></div><p style="text-align:left;"><span style="color:inherit;"><br></span></p><div style="text-align:left;">Key selling points:</div><ol><li style="text-align:left;">Documentation looked good with plenty of examples – this was critical since I was starting from zero and needed to get up to speed quickly;<br></li><li style="text-align:left;">Has a Python interface, which is the only programming language I consider myself a capable developer in;&nbsp;<br></li><li style="text-align:left;">Supports a number of solver back-ends; although I did not get a chance to try this out; and</li><li style="text-align:left;">If Google uses it, it must be good... right?</li></ol><p style="text-align:left;"><br></p><p style="text-align:left;">As someone who has more experience with Stats/Machine Learning models, Constraint Optimisation presented an interesting challenge given the way models need to be defined;&nbsp;<br></p><div style="text-align:left;"><ul><li style="text-align:left;">Variables must be integers, this means multiplying decimal variables to a magnitude that allows the truncation of the decimal component.</li><li>Expression are in the form of linear equations, which creates some limitations. For example you are unable to simply multiply variables within the same expression such as y = a * b, however you can work around this; in this case one has to use a function cp_model.AddProdEquality(, [])</li></ul></div><p style="text-align:left;"><span style="color:inherit;"><br></span></p><div style="text-align:left;">To note however, that the CP-SAT solver although superior, has a different Python API to the previous CP Solver which (on face value) appeared to have more flexibility in how equations could be constructed.</div><p style="text-align:left;"><span style="color:inherit;"><br></span></p><div style="text-align:left;">Also, more generally, when referring to the API docs (which are presented in C++) there appears to be certain things that are either not represented in the Python API, or not well documented to understand how it should be used.</div><p style="text-align:left;"><span style="color:inherit;"><br></span></p><div style="text-align:left;"><div>I’ll dig into things a bit further in future posts as I’d like pursue some experimentation to understand pros and cons of different approaches. In the meantime check out the <a href="https://developers.google.com/optimization/cp/cp_solver" title="examples" target="_blank">examples</a>, they really are quite comprehensive for standard problems.</div></div><p style="text-align:left;"><span style="color:inherit;"><br></span></p><div style="text-align:left;">As a postscript, the project was successfully delivered using OR-Tools , however due to the modeled variables and constraints, solution speed was pretty slow. This was not unexpected and not a reflection of OR-Tools since the model contained thousands of variables … but it would have been nice to find a silver bullet!</div><div style="text-align:left;"><br></div></div>
</div></div></div></div></div></div> ]]></content:encoded><pubDate>Thu, 02 May 2019 10:18:04 +0930</pubDate></item><item><title><![CDATA[Grouping Data by Attribute Using Lag & Cumulative Sum]]></title><link>https://www.prescient.consulting/blogs/post/Grouping-Data-by-Attribute</link><description><![CDATA[<img align="left" hspace="5" src="https://www.prescient.consulting/files/blog_img/sql-1-banner.PNG"/>Simple way of use the lag function to create groups within data.]]></description><content:encoded><![CDATA[<div class="zpcontent-container blogpost-container "><div data-element-id="elm_IwVMQ-hxS1yGN6kQIW4yWw" data-element-type="section" class="zpsection "><style type="text/css"></style><div class="zpcontainer-fluid zpcontainer"><div data-element-id="elm_jjOzznymT7yPhZ1LH9dQ0w" data-element-type="row" class="zprow zprow-container zpalign-items- zpjustify-content- " data-equal-column=""><style type="text/css"></style><div data-element-id="elm__pWhpRPGThO9fSr6OBcBoQ" data-element-type="column" class="zpelem-col zpcol-12 zpcol-md-12 zpcol-sm-12 zpalign-self- "><style type="text/css"></style><div data-element-id="elm_RX4uz2MnRRefkdHtDMTjnQ" data-element-type="text" class="zpelement zpelem-text "><style></style><div class="zptext zptext-align-center " data-editor="true"><p style="text-align:left;">A fair proportion of my work involves aspects of data quality i.e. munging data.</p><p style="text-align:left;">Routinely, there is a requirement to identify duplicate groups of records.</p><p><span style="color:inherit;"></span></p><p style="text-align:left;">The following is a snippet that creates group ids from which further processing can be performed</p></div>
</div><div data-element-id="elm_D8gelKuyhjwf8ghNs1w19g" data-element-type="text" class="zpelement zpelem-text "><style></style><div class="zptext zptext-align-left " data-editor="true"><p><span style="color:inherit;"></span></p><p>1.<span style="font-size:7pt;">&nbsp; </span>Setup an example table</p></div>
</div><div data-element-id="elm_cehI1dwt3I3GZrf2oJR95w" data-element-type="text" class="zpelement zpelem-text code-block "><style></style><div class="zptext zptext-align-left " data-editor="true"><p><span style="color:inherit;"></span></p><pre><div><span style="font-family:&quot;Courier New&quot;;">create table #tmp_cust (</span></div><div><span style="font-family:&quot;Courier New&quot;;">&nbsp; id int,</span></div><div><span style="font-family:&quot;Courier New&quot;;">&nbsp; group_field varchar(max),</span></div><div><span style="font-family:&quot;Courier New&quot;;">);</span></div><span style="font-family:&quot;Courier New&quot;;"><br></span><div><span style="font-family:&quot;Courier New&quot;;">insert into #tmp_cust values (1, 'attr1');</span></div><div><span style="font-family:&quot;Courier New&quot;;">insert into #tmp_cust values (2, 'attr1');</span></div><div><span style="font-family:&quot;Courier New&quot;;">insert into #tmp_cust values (3, 'attr1');</span></div><div><span style="font-family:&quot;Courier New&quot;;">insert into #tmp_cust values (4, 'attr2');</span></div><div><span style="font-family:&quot;Courier New&quot;;">insert into #tmp_cust values (5, 'attr2');</span></div><div><span style="font-family:&quot;Courier New&quot;;">insert into #tmp_cust values (6, 'attr3');</span></div></pre></div>
</div><div data-element-id="elm_3dfAmfqt4PMCXSj2UNZKUA" data-element-type="text" class="zpelement zpelem-text "><style></style><div class="zptext zptext-align-left " data-editor="true"><p><span style="color:inherit;"></span></p><p>2.<span style="font-size:7pt;">&nbsp; </span>Use the lag function to determine when a the group field changes</p></div>
</div><div data-element-id="elm_GdR6yMMb9LnnmWoUATkn7w" data-element-type="text" class="zpelement zpelem-text code-block "><style></style><div class="zptext zptext-align-left " data-editor="true"><div><span style="font-family:&quot;Courier New&quot;;">with lagged as (</span></div><div><span style="font-family:&quot;Courier New&quot;;">&nbsp; &nbsp; select</span></div><div><span style="font-family:&quot;Courier New&quot;;">&nbsp; &nbsp; id</span></div><div><span style="font-family:&quot;Courier New&quot;;">&nbsp; &nbsp; , group_field</span></div><div><span style="font-family:&quot;Courier New&quot;;">&nbsp; &nbsp; , case when group_field &lt;&gt; lag(group_field) over (partition by 1 order by group_field, id) then 1 else 0 end as Group_Flag</span></div><div><span style="font-family:&quot;Courier New&quot;;">&nbsp; from #tmp_cust tc</span></div><div><span style="font-family:&quot;Courier New&quot;;">)</span></div></div>
</div><div data-element-id="elm_IO3qixQ8eAqrV1uSe-CV_g" data-element-type="text" class="zpelement zpelem-text "><style></style><div class="zptext zptext-align-left " data-editor="true"><p><span style="color:inherit;"></span></p><p>3.<span style="font-size:7pt;">&nbsp; </span>Use a cumulative sum; achieved by rows unbounded preceding in the window function.</p></div>
</div><div data-element-id="elm_iJO4mw1OBHiHj-7vWNvUIQ" data-element-type="text" class="zpelement zpelem-text code-block "><style></style><div class="zptext zptext-align-left " data-editor="true"><div><span style="font-family:&quot;Courier New&quot;;">select</span></div><div><span style="font-family:&quot;Courier New&quot;;">&nbsp; id</span></div><div><span style="font-family:&quot;Courier New&quot;;">&nbsp; , group_field</span></div><div><span style="font-family:&quot;Courier New&quot;;">&nbsp; , sum(Group_Flag) over (order by group_field, id rows unbounded preceding ) as Group_Flag</span></div><div><span style="font-family:&quot;Courier New&quot;;">from lagged</span></div></div>
</div><div data-element-id="elm_depAIGhWQRIY6ByffSIDUA" data-element-type="text" class="zpelement zpelem-text "><style></style><div class="zptext zptext-align-left " data-editor="true"><p>Results:</p><p><img src="/files/blog_img/grouping-results.PNG"><br></p></div>
</div><div data-element-id="elm_NjvDkJcfMk2mwjEd0P5j8Q" data-element-type="text" class="zpelement zpelem-text "><style></style><div class="zptext zptext-align-left " data-editor="true"><p><span style="color:inherit;"></span></p><p>With the groups identified we can then move onto removing/remediation of duplicates!</p><p><br></p><p>(Tested using SQL Server 2016)</p></div>
</div></div></div></div></div></div> ]]></content:encoded><pubDate>Thu, 21 Feb 2019 15:11:54 +1030</pubDate></item><item><title><![CDATA[GnuGPG - How to fix gpg: handle plaintext failed: General error]]></title><link>https://www.prescient.consulting/blogs/post/GnuGPG-General-error</link><description><![CDATA[How to fix gpg: handle plaintext failed: General error]]></description><content:encoded><![CDATA[<div class="zpcontent-container blogpost-container "><div data-element-id="elm_TIB52KYdRRWVbNz8Q_snhg" data-element-type="section" class="zpsection "><style type="text/css"></style><div class="zpcontainer-fluid zpcontainer"><div data-element-id="elm_EjeyH10URzuLbRG_g7J43w" data-element-type="row" class="zprow zprow-container zpalign-items- zpjustify-content- " data-equal-column=""><style type="text/css"></style><div data-element-id="elm_TVnYzvUAQ-Gqq84oBrLc9Q" data-element-type="column" class="zpelem-col zpcol-12 zpcol-md-12 zpcol-sm-12 zpalign-self- "><style type="text/css"></style><div data-element-id="elm_1q7pM_zTRmioNXfcqEGEjg" data-element-type="text" class="zpelement zpelem-text "><style></style><div class="zptext zptext-align-center " data-editor="true"><p style="text-align:left;"><span style="color:inherit;">[Note: this issue occured using GPG4Win 2.2.5 in an Azure Function App environment]</span><br></p><p style="text-align:left;"><span style="color:inherit;"><br></span></p><p style="text-align:left;">I recently encountered a frustrating, albeit minor, issue. A Powershell Script process that was running on as an Azure Function App, started throwing an error <i>gpg: handle plaintext failed: General error</i>.&nbsp;</p><p style="text-align:left;"><br></p><p style="text-align:left;">A quick Google search of the error message did not reveal much, though the first result did refer to filenames potentially being a cause.</p><p style="text-align:left;"><br></p><p style="text-align:left;">The frustrating part was that it was working correctly previously, and on my local environment there was no issue in the command I was using: <i>bin\gpg.exe -v --batch --output d:\home\download\files\file_07112018.zip --decrypt D:\home\download\files\file_07112018.zip.gpg</i></p><p style="text-align:left;"><i><br></i></p><p><span style="color:inherit;"></span></p><p style="text-align:left;">Long story (of trying error logging, different switches etc) short, I altered the output filename and placed an underscore suffix and magically it worked! A guess is a conflict between the filename set in the encrypted file since it was the same as I was trying to output.</p><p style="text-align:left;"><br></p><p style="text-align:left;">Hope this helps someone!</p></div>
</div></div></div></div></div></div> ]]></content:encoded><pubDate>Wed, 23 Jan 2019 08:34:47 +1030</pubDate></item><item><title><![CDATA[Grouping Temporal Sequences in SQL]]></title><link>https://www.prescient.consulting/blogs/post/Grouping-Temporal-Sequences-in-SQL</link><description><![CDATA[<img align="left" hspace="5" src="https://www.prescient.consulting/files/blog_img/sql-1-banner.PNG"/>How to group transaction records into sequences using SQL.]]></description><content:encoded><![CDATA[<div class="zpcontent-container blogpost-container "><div data-element-id="elm_FdKAJVyxQFe-MHgyEsc5Kg==" data-element-type="section" class="zpsection "><style type="text/css"></style><div class="zpcontainer-fluid zpcontainer"><div data-element-id="elm_bYVjDFjRTeGQ9G9UwPFw-g==" data-element-type="row" class="zprow zprow-container zpalign-items- zpjustify-content- " data-equal-column=""><style type="text/css"></style><div data-element-id="elm_iLLZeejATDKE1o9sxZCoKA==" data-element-type="column" class="zpelem-col zpcol-12 zpcol-md-12 zpcol-sm-12 zpalign-self- "><style type="text/css"></style><div data-element-id="elm_W7otbTKNRzyO5Z--u8HBDQ==" data-element-type="text" class="zpelement zpelem-text "><style></style><div class="zptext zptext-align-center " data-editor="true"><div style="text-align:left;">I was recently working in a PostgreSQL (9.6) environment and had one of those problems that comes around infrequently enough that it isn't a worn pattern in my brain. Contributing to this is the fact that I dwelt for a long time in SQL Server 2008 land which lacked a lot of functionality (lead/lag functions) that have been in the wild for quite a while.</div><p style="text-align:left;"><br></p><div style="text-align:left;"><div><span style="font-weight:700;">Problem: </span>Temporal transaction data that needed to be grouped into&nbsp;sequences. In this scenario, there is also an additional column by which the data is to be grouped.</div></div><div style="text-align:left;"><br></div><p style="text-align:left;">The set-up code to demonstrate the approach:&nbsp;</p></div>
</div><div data-element-id="elm_tqqm6uq0ji9oCEdM8UCHsg" data-element-type="text" class="zpelement zpelem-text code-block "><style></style><div class="zptext zptext-align-left " data-editor="true"><p><span style="color:inherit;"></span></p><pre style="font-size:7.2pt;"><p><span style="color:inherit;"></span></p><pre><pre style="font-size:7.2pt;"><p><span style="color:inherit;"></span></p><pre><span style="font-size:12px;font-family:&quot;Courier New&quot;;"><span style="font-weight:bold;">drop table if exists </span>seq_demo<br>;<br><span style="font-weight:bold;">create table </span>seq_demo (<br>    dt <span style="font-weight:bold;">date<br>    </span>, <span style="font-weight:bold;">grouping character varying<br></span>);<br><span style="font-weight:bold;">insert into </span>seq_demo <span style="font-weight:bold;">values </span>('2018-01-01', 'grp1');<br><span style="font-weight:bold;">insert into </span>seq_demo <span style="font-weight:bold;">values </span>('2018-01-02', 'grp1');<br><span style="font-weight:bold;">insert into </span>seq_demo <span style="font-weight:bold;">values </span>('2018-01-04', 'grp1');<br><span style="font-weight:bold;">insert into </span>seq_demo <span style="font-weight:bold;">values </span>('2018-01-05', 'grp1');<br><span style="font-weight:bold;">insert into </span>seq_demo <span style="font-weight:bold;">values </span>('2018-01-06', 'grp1');</span></pre><pre style="font-size:7.2pt;"><pre><span style="font-size:12px;font-family:&quot;Courier New&quot;;"><span style="font-weight:bold;">insert into </span>seq_demo <span style="font-weight:bold;">values </span>('2018-01-03', 'grp2');</span></pre><span style="font-family:&quot;Courier New&quot;;"><span style="font-size:12px;"><span style="font-weight:bold;">insert into </span>seq_demo <span style="font-weight:bold;">values </span>('2018-01-07', 'grp2');<br><span style="font-weight:bold;">insert into </span>seq_demo <span style="font-weight:bold;">values </span>('2018-01-08', 'grp2');<br><span style="font-weight:bold;">insert into </span>seq_demo <span style="font-weight:bold;">values </span>('2018-01-09', 'grp2');<br><span style="font-weight:bold;">insert into </span>seq_demo <span style="font-weight:bold;">values </span>('2018-01-10', 'grp2')</span><span style="font-size:12px;">;</span></span><br></pre></pre></pre></pre></div>
</div><div data-element-id="elm_qimIS66jLUYxF0AnDNX6Jg" data-element-type="text" class="zpelement zpelem-text "><style></style><div class="zptext zptext-align-left " data-editor="true"><p>The above test data creates four sequences across the two groupings: { 'grp1', 'grp2' }</p><p>And we would like to transform this into the following output:</p></div>
</div><div data-element-id="elm_jvhrJsxen7gYzAvnEpJnAA" data-element-type="table" class="zpelement zpelem-table "><style type="text/css"> [data-element-id="elm_jvhrJsxen7gYzAvnEpJnAA"] .zptable{ width:75% !important; } </style><div class="zptable zptable-align-center zptable-header-light zptable-header-none zptable-cell-outline-on zptable-outline-on zptable-style- " data-width="75" data-editor="true"><table style="width:75%;"><tbody><tr style="height:23px;"><td style="width:12.9911%;"><span style="font-size:12px;"> 1</span></td><td style="width:17.9823%;"><span style="font-size:12px;"> grp1</span></td><td style="width:34.1108%;"><span style="font-size:12px;"> 2018-01-01</span></td><td style="width:30.6122%;"><span style="font-size:12px;">  2018-01-02</span></td></tr><tr style="height:37.6px;"><td style="width:12.9911%;"><span style="font-size:12px;"> 2</span></td><td style="width:17.9823%;"><span style="font-size:12px;"> grp1</span></td><td style="width:34.1108%;"><span style="font-size:12px;"> 2018-01-04</span></td><td style="width:30.6122%;"><span style="font-size:12px;"> 2018-01-06</span></td></tr><tr><td style="width:12.9911%;"><span style="font-size:12px;"> 3</span></td><td style="width:17.9823%;"><span style="font-size:12px;"> grp2</span></td><td style="width:34.1108%;"><span style="font-size:12px;"> 2018-01-03</span></td><td style="width:30.6122%;"><span style="font-size:12px;"> 2018-01-03</span></td></tr><tr><td style="width:12.9911%;"><span style="font-size:12px;"> 4</span></td><td style="width:17.9823%;"><span style="font-size:12px;">grp2</span></td><td style="width:34.1108%;"><span style="font-size:12px;"> 2018-01-07</span></td><td style="width:30.6122%;"><span><span style="font-size:12px;">  2018-</span><span style="font-size:12px;">01-10</span></span></td></tr></tbody></table></div>
</div><div data-element-id="elm_hE5DJptJssu_MmbPnBKf6Q" data-element-type="text" class="zpelement zpelem-text "><style></style><div class="zptext zptext-align-left " data-editor="true"><p>This is one approach that makes use of the <span style="font-style:italic;"><a href="https://www.postgresql.org/docs/current/static/functions-window.html" title="PostgreSQL Window Functions" target="_blank" rel="nofollow">lag</a></span> function, following by a cumulative (windowed) <span style="font-style:italic;color:rgb(231, 31, 53);">sum </span>to create the groups.</p></div>
</div><div data-element-id="elm_fLqSLvQdLsIVQlGebthLYw" data-element-type="text" class="zpelement zpelem-text code-block "><style></style><div class="zptext zptext-align-left " data-editor="true"><pre style="font-size:7.2pt;"><pre style="font-size:7.2pt;"><pre style="font-size:7.2pt;"><pre><span style="font-size:12px;font-family:&quot;Courier New&quot;;"><span style="font-weight:bold;">with </span>lagged <span style="font-weight:bold;">as </span>(<br>    <span style="font-weight:bold;">select<br>        </span>dt<br>        , <span style="font-weight:bold;">grouping<br>        </span>, <span style="font-style:italic;">lag</span>(dt) <span style="font-weight:bold;">over </span>(<span style="font-weight:bold;">partition by grouping order by </span>dt) <span style="font-weight:bold;">as </span>lagged_dt<br>        -- the rn preserves row order for the next step, which is sometimes desired<br>        , <span style="font-style:italic;">row_number</span>() <span style="font-weight:bold;">over </span>(<span style="font-weight:bold;">partition by grouping order by </span>dt) <span style="font-weight:bold;">as </span>rn<br>    <span style="font-weight:bold;">from </span>seq_demo<br>)</span></pre><pre><span style="font-size:12px;font-family:&quot;Courier New&quot;;">, grouped <span style="font-weight:bold;">as </span>(<br>    <span style="font-weight:bold;">select<br>        </span>dt<br>        , <span style="font-weight:bold;">grouping<br>        </span>, lagged_dt<br>        , (dt - lagged_dt) <span style="font-weight:bold;">as </span>days_diff<br>        , <span style="font-weight:bold;">case when </span>lagged_dt <span style="font-weight:bold;">is null or </span>(dt - lagged_dt) &gt; 1 <span style="font-weight:bold;">then </span>1 <span style="font-weight:bold;">else </span>0 <span style="font-weight:bold;">end as </span>changed_dt<br>        , <span style="font-style:italic;">sum</span>(<span style="font-weight:bold;">case when </span>lagged_dt <span style="font-weight:bold;">is null or </span>(dt - lagged_dt) &gt; 1 <span style="font-weight:bold;">then </span>1 <span style="font-weight:bold;">else </span>0 <span style="font-weight:bold;">end</span>)<br>           <span style="font-weight:bold;">over </span>(<span style="font-weight:bold;">partition by grouping order by </span>rn <span style="font-weight:bold;">rows between unbounded preceding and current row</span>) <span style="font-weight:bold;">as </span>dt_group<br>        -- note on postgresql &quot;rows between unbounded preceding and current row&quot; was not required<br><br>    <span style="font-weight:bold;">from </span>lagged<br>)</span></pre><pre style="font-size:7.2pt;"><span style="font-family:&quot;Courier New&quot;;"><br></span></pre></pre><span style="color:inherit;font-size:12px;font-family:&quot;Courier New&quot;;"><pre style="font-size:7.2pt;"><span style="font-weight:bold;">select<br>    grouping<br>    </span>, dt_group<br>    , <span style="font-style:italic;">min</span>(dt) <span style="font-weight:bold;">as </span>start_dt<br>    , <span style="font-style:italic;">max</span>(dt) <span style="font-weight:bold;">as </span>end_dt</pre><pre style="font-size:7.2pt;"><br><span style="font-weight:bold;">from </span>grouped<br><br><span style="font-weight:bold;">group by<br>    grouping<br>    </span>, dt_group<br><br><span style="font-weight:bold;">order by<br>    grouping<br>    </span>, dt_group<br>;</pre></span></pre></pre></div>
</div><div data-element-id="elm_yPWVAT6IJsFB74m4tKj6pA" data-element-type="text" class="zpelement zpelem-text "><style></style><div class="zptext zptext-align-left " data-editor="true"><p>My results:</p></div>
</div><div data-element-id="elm_Bur2fr2N-Ayrsz0CV0ottw" data-element-type="image" class="zpelement zpelem-image "><style></style><div data-caption-color="" data-size-tablet="" data-size-mobile="" data-align="center" data-tablet-image-separate="" data-mobile-image-separate="" class="zpimage-container zpimage-align-center zpimage-size-original zpimage-tablet-fallback-original zpimage-mobile-fallback-original hb-lightbox " data-lightbox-options="
                type:fullscreen,
                theme:dark"><figure role="none" class="zpimage-data-ref"><span class="zpimage-anchor" role="link" tabindex="0" aria-label="Open Lightbox" style="cursor:pointer;"><picture><img class="zpimage zpimage-style-none zpimage-space-none " src="/files/blog_img/sql-1-results.PNG" size="original" data-lightbox="true"/></picture></span></figure></div>
</div><div data-element-id="elm_MOEbLlPphxDONalsxls6QQ" data-element-type="text" class="zpelement zpelem-text "><style></style><div class="zptext zptext-align-left " data-editor="true"><p>The specific use case this solved was to identify isolated transactions that had a group count of 1.&nbsp;</p><p><br></p><p>This pattern also works well to condense repeated dimensional data that appears in a transactional form.</p></div>
</div></div></div></div></div></div> ]]></content:encoded><pubDate>Mon, 08 Oct 2018 22:45:00 +1030</pubDate></item><item><title><![CDATA[Hello World]]></title><link>https://www.prescient.consulting/blogs/post/Hello-World</link><description><![CDATA[<img align="left" hspace="5" src="https://www.prescient.consulting/files/new-logo-favicon-sm3.png"/>Hello World post]]></description><content:encoded><![CDATA[<div class="zpcontent-container blogpost-container "><div data-element-id="elm_g9c3js4US6e1-frp1Ff58A==" data-element-type="section" class="zpsection "><style type="text/css"></style><div class="zpcontainer-fluid zpcontainer"><div data-element-id="elm_GWuF-xsJQFq9mu_W0HpIhw==" data-element-type="row" class="zprow zprow-container zpalign-items- zpjustify-content- " data-equal-column=""><style type="text/css"></style><div data-element-id="elm_Q9rI1j0vToG72eyxyJFV1A==" data-element-type="column" class="zpelem-col zpcol-12 zpcol-md-12 zpcol-sm-12 zpalign-self- zpdefault-section zpdefault-section-bg "><style type="text/css"> [data-element-id="elm_Q9rI1j0vToG72eyxyJFV1A=="].zpelem-col{ background-color:#000000; background-image:unset; } </style><div data-element-id="elm_P7-KoAphR_uNNU_M3icIVQ==" data-element-type="heading" class="zpelement zpelem-heading "><style></style><h2
 class="zpheading zpheading-align-left " data-editor="true"><span style="font-family:&quot;Courier New&quot;;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:rgb(236, 240, 241);">&nbsp; &nbsp;&gt;&gt;&gt; print('Hello World')<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Hello World</span></span><br></h2></div>
<div data-element-id="elm_-3ELBVrON_ajQoy73JGHow" data-element-type="spacer" class="zpelement zpelem-spacer "><style> div[data-element-id="elm_-3ELBVrON_ajQoy73JGHow"] div.zpspacer { height:8px; } @media (max-width: 768px) { div[data-element-id="elm_-3ELBVrON_ajQoy73JGHow"] div.zpspacer { height:calc(8px / 3); } } </style><div class="zpspacer " data-height="8"></div>
</div></div></div></div></div></div> ]]></content:encoded><pubDate>Wed, 03 Oct 2018 14:29:11 +0930</pubDate></item></channel></rss>