<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Davide Mauri</title>
    <description>The latest articles on DEV Community by Davide Mauri (@yorek).</description>
    <link>https://dev.to/yorek</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F332137%2F05a2cc11-c789-47fb-9c43-a5b13ba86e7b.jpeg</url>
      <title>DEV Community: Davide Mauri</title>
      <link>https://dev.to/yorek</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yorek"/>
    <language>en</language>
    <item>
      <title>Retrieval Augmented Generation with Azure SQL</title>
      <dc:creator>Davide Mauri</dc:creator>
      <pubDate>Thu, 29 Aug 2024 21:22:23 +0000</pubDate>
      <link>https://dev.to/azure/retrieval-augmented-generation-with-azure-sql-63m</link>
      <guid>https://dev.to/azure/retrieval-augmented-generation-with-azure-sql-63m</guid>
      <description>&lt;p&gt;Retrieval Augmented Generation, or RAG, is one of the hottest topics at the moment as it opens up the possibility of interacting with data using natural language, which is a long-time dream finally coming true.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3j1q87pthpkr3o031jkj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3j1q87pthpkr3o031jkj.png" alt="RAG Sample on a terminal" width="800" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is very likely that a lot of your data is already stored or will be stored in Azure SQL, so a common request is to have an example on how to apply the RAG pattern to your own data stored an Azure SQL database.&lt;/p&gt;

&lt;p&gt;This blog post is all about that. Let's start from the basics and make sure the RAG pattern is clearly understood.&lt;/p&gt;

&lt;h2&gt;
  
  
  RAG Pattern 101
&lt;/h2&gt;

&lt;p&gt;To make the explanation easy to understand, even if you are completely new to the topic, let's start from a simple scenario. You have a database where you have stored details - title, abstract, time, speakers - of all the session of a conference. A good example could be the just passed &lt;a href="https://focus.dotnetconf.net/" rel="noopener noreferrer"&gt;.NET Focus on AI&lt;/a&gt; conference or the forthcoming &lt;a href="https://www.dotnetconf.net/" rel="noopener noreferrer"&gt;.NET Conf 2024&lt;/a&gt; conference, or one of my favorites, the &lt;a href="https://vslive.com/Home.aspx" rel="noopener noreferrer"&gt;VS Live&lt;/a&gt; conference.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why RAG?
&lt;/h3&gt;

&lt;p&gt;You already know that Language Models like &lt;a href="https://openai.com/index/gpt-4/" rel="noopener noreferrer"&gt;GPT-4&lt;/a&gt; or &lt;a href="https://azure.microsoft.com/en-us/blog/introducing-phi-3-redefining-whats-possible-with-slms/" rel="noopener noreferrer"&gt;Phi-3&lt;/a&gt; can accept any text you'll provide them, and they can generate answer to almost any question you may want to ask. So, why a specific pattern like RAG is needed? Why can't we just send all the titles and the abstract and all the information stored in the database to the LM and call it a day? Then we could ask anything using a simple API call and our work we'll be done.&lt;/p&gt;

&lt;p&gt;There are two reasons why you don't want to do that.&lt;/p&gt;

&lt;p&gt;First of all, if you are asking something related to Blazor, there is no need to give the LM details about a session that is completely out of scope: it will not help the LM to answer and could actually make the answer less precise (see: "&lt;a href="https://huggingface.co/papers/2307.03172" rel="noopener noreferrer"&gt;Lost in the Middle: How Language Models Use Long Contexts&lt;/a&gt;"). Secondly, the cost of an AI call is based on how many &lt;a href="https://learn.microsoft.com/en-us/azure/azure-sql/database/ai-artificial-intelligence-intelligent-applications?view=azuresql#tokens/" rel="noopener noreferrer"&gt;tokens&lt;/a&gt; the sent text must be split into - tokenization is something that happen transparently behind the scenes - and so the less text you send, the less token you'll be sending, which means that you'll be using less resources. More efficiency, less digital waste (which means less power consumed), lower price to pay for: it's a win for everyone!&lt;/p&gt;

&lt;h3&gt;
  
  
  RAG Steps
&lt;/h3&gt;

&lt;p&gt;The first step of the RAG pattern is to filter out all the data that is not relevant to the question being asked. For this first step, typically, a semantic search is performed on the text. To do a semantic search, &lt;a href="https://learn.microsoft.com/en-us/azure/azure-sql/database/ai-artificial-intelligence-intelligent-applications?view=azuresql#embeddings" rel="noopener noreferrer"&gt;embeddings&lt;/a&gt;, and thus vectors, are used to do &lt;a href="https://learn.microsoft.com/en-us/azure/azure-sql/database/ai-artificial-intelligence-intelligent-applications?view=azuresql#vector-search" rel="noopener noreferrer"&gt;vector similarity&lt;/a&gt; search and return only the relevant results. Since Azure SQL is a powerful modern relational and multi-model database, you can enrich vector search other all other filtering capabilities that it has already. Filtering by exact values (for example all sessions on a certain day), by JSON data (for example sessions with certain tags) or even using geospatial filters (for example session delivered withing 1 km from me).&lt;/p&gt;

&lt;p&gt;Once you have the relevant data you can then efficiently send it to the LM, along with the question you want to ask, to have the answer in natural language, without wasting resources and money.&lt;/p&gt;

&lt;p&gt;A diagram that shows the two steps of the RAG pattern is here so that you can easily visualize the process and see how it is applied to the sample data we're using in this post.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35q5f1z3snawcnyplhyr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35q5f1z3snawcnyplhyr.png" alt="High-Level RAG Pattern Diagram" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you are familiar with the RAG pattern, is time to see how it can be realized using Azure services.&lt;/p&gt;

&lt;h2&gt;
  
  
  RAG pattern in Azure
&lt;/h2&gt;

&lt;p&gt;There are many ways to implement the RAG pattern in Azure. I personally love the serverless approach provided by the cloud, so I'm using serverless services in this sample. If you prefer a containerized approach, keep in mind that everything described here can be easily hosted in a container, if you prefer to do so.&lt;/p&gt;

&lt;p&gt;The high-level architecture of the RAG pattern applied to Azure is the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk4tpzd7vejzydprevvx3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk4tpzd7vejzydprevvx3.png" alt="High-Level Solution Architecture on Azure" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Azure Services being used are:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/static-web-apps/overview" rel="noopener noreferrer"&gt;Azure Static Web Apps&lt;/a&gt;&lt;br&gt;
&lt;a href="https://learn.microsoft.com/azure/ai-services/openai/" rel="noopener noreferrer"&gt;Azure OpenAI&lt;/a&gt;&lt;br&gt;
&lt;a href="https://learn.microsoft.com/azure/azure-functions/functions-overview?pivots=programming-language-csharp" rel="noopener noreferrer"&gt;Azure Functions&lt;/a&gt;&lt;br&gt;
&lt;a href="https://learn.microsoft.com/azure/azure-functions/functions-bindings-azure-sql-trigger" rel="noopener noreferrer"&gt;Azure Functions SQL Trigger Binding&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.sqlservercentral.com/articles/the-sql-developer-experience-beyond-rdbms" rel="noopener noreferrer"&gt;Azure SQL Database&lt;/a&gt;&lt;br&gt;
&lt;a href="https://aka.ms/dab" rel="noopener noreferrer"&gt;Data API builder&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Frontend
&lt;/h2&gt;

&lt;p&gt;The fronted is a simple React application hosted in Azure Static Web Apps. It is used to allow users to ask a question that will then be answered applying the RAG pattern. There is also the option to just do similarity search to clearly see the difference in terms of response between a simple similarity search and the full RAG pattern.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5k9swouya2np4qr39o84.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5k9swouya2np4qr39o84.png" alt="UI's Screenshot" width="800" height="120"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Backend
&lt;/h2&gt;

&lt;p&gt;Azure Functions are used to handle the question asked by the user and to orchestrate the RAG pattern. Once the question is asked, the Azure Function called will do similarity search in Azure SQL, then pack the results into a pipe-separated format&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;&lt;span class="nv"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sessions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nv"&gt;"{s.Title}|{s.Abstract}|{s.Speakers}|{s.Start}|{s.End}"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then send the question, the list of session and the following prompt to the LM, hosted in Azure OpenAI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"You are a system assistant who helps users find the right session to watch from the conference, based off the sessions that are provided to you. Sessions will be provided in an assistant message in the format of `title|abstract|speakers|start-time|end-time`. You can use only the provided session list to help you answer the user's question. If the user asks a question that is not related to the provided sessions, you can respond with a message that you can't help with that question."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Data API builder is used to easily expose stored procedures that are called via REST calls from the frontend to show how many sessions have been indexes (in the “About” tab) and to call the find_session procedure that does vector search (available in the “Search” tab). Data API builder automatically expose desired database objects as REST or GraphQL endpoints, which is great to quickly deploy a CRUD service that can be called by any framework, in just a few minutes.&lt;/p&gt;

&lt;p&gt;Azure Functions are also used to immediately turn session title and abstract into an embedding as soon changes are made to the database table. This is done by calling Azure OpenAI embedding model. &lt;a href="https://learn.microsoft.com/azure/azure-functions/functions-bindings-azure-sql-trigger" rel="noopener noreferrer"&gt;Azure SQL Trigger Binding&lt;/a&gt; is what make possible to have tables monitored for changes and then react to those changes by executing some code in the Azure Function itself. It is extremely lightweight (it uses native &lt;a href="https://learn.microsoft.com/en-us/sql/relational-databases/track-changes/about-change-tracking-sql-server?view=sql-server-ver16" rel="noopener noreferrer"&gt;Azure SQL Change Tracking&lt;/a&gt; capabilities behind the scenes) and it provides all the flexibility and computation power needed for almost anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Database
&lt;/h2&gt;

&lt;p&gt;Azure SQL's support for natively storing and querying vectors is in &lt;a href="https://devblogs.microsoft.com/azure-sql/announcing-eap-native-vector-support-in-azure-sql-database/" rel="noopener noreferrer"&gt;Early Adopter Preview&lt;/a&gt;. It includes the ability to store vectors in a compact binary format and to calculate distance between two vectors - and thus calculate the semantic similarity of related topics as vectors in this sample are the embeddings of session title and abstract - so that filtering only the relevant session given a user query is as easy as writing the following query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;vector_distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cosine'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;qv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cosine_distance&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt;
    &lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sessions&lt;/span&gt;
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt;
    &lt;span class="n"&gt;cosine_distance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the query will return the 10 most similar sessions, given the search vector &lt;a class="mentioned-user" href="https://dev.to/qv"&gt;@qv&lt;/a&gt; that contains the embedding of the topic being searched. Getting the embeddings for some text can be done in many ways with many languages, but at the end of the day is just a REST call, so in Azure SQL it can be easily done using sp_invoke_external_rest_endpoint as shown in this sample &lt;a href="https://devblogs.microsoft.com/azure-sql/announcing-eap-native-vector-support-in-azure-sql-database/#using-a-rest-service-to-get-embeddings" rel="noopener noreferrer"&gt;Get_Embeddings&lt;/a&gt; procedure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code and Demo
&lt;/h2&gt;

&lt;p&gt;That's it. Implementing the RAG pattern in Azure SQL is incredibly easy. If you want to see it by yourself, I've presented about this topic just a few days ago at .NET Conf Focus on AI, where I demoed the full end-to-end pattern. You can get the repo and run the demo either locally (except for Azure SQL DB, but hey! there is a free tier for that!) or in Azure and then from there you can start to use your data instead of the sample demo data provided and you'll be on a good path already for allowing your users to chat with your data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/q9R2m7UIn-o?list=PLdo4fOcmZ0oX7Yg1cixIj6hXjz9C5MHJR" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F50nmovg74t5s8lnkx2u7.png" alt="YouTube Video Screenshot" width="794" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;For this sample, as you have noticed, I used SQL and .NET directly, even though there are many libraries out there that are trying to abstract and simplify the whole process. My goal for this post was to make sure that you learn and understand how things work behind the scenes so when you'll be using any of the amazing libraries available (be it Semantic Kernel or LangChain) they will not be just a magic black box, but you know exactly what is happening behind the scenes.&lt;/p&gt;

&lt;p&gt;And, anyway, samples using those libraries I just mentioned will follow soon, so stay tuned!&lt;/p&gt;

</description>
      <category>azure</category>
      <category>database</category>
      <category>dotnet</category>
      <category>ai</category>
    </item>
    <item>
      <title>Share your dev wishes 👍</title>
      <dc:creator>Davide Mauri</dc:creator>
      <pubDate>Tue, 13 Feb 2024 16:04:51 +0000</pubDate>
      <link>https://dev.to/yorek/share-your-developer-wishes-1m01</link>
      <guid>https://dev.to/yorek/share-your-developer-wishes-1m01</guid>
      <description>&lt;p&gt;🚨 🚨 🚨 CALLING ALL DEVELOPERS!!! 🚨 🚨 🚨&lt;/p&gt;

&lt;p&gt;Are you building applications with Databases? 👍 Help us understand how we can make the Azure SQL Database the best place for your developers 👨‍💻 👩‍💻 to be productive, guaranteeing scalability 📈, performance 🚀 and security 🔒, so that you can grow with peace of mind 😃. Fill out this form here and help to shape the future of Azure SQL as you would like it to be!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aka.ms/datadevlist"&gt;https://aka.ms/datadevlist&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks to your feedback in the last years we added quite a lot of new stuff the developers &lt;em&gt;loved&lt;/em&gt;. From the ability to call a REST API right from Azure SQL with the &lt;a href="https://learn.microsoft.com/sql/relational-databases/system-stored-procedures/sp-invoke-external-rest-endpoint-transact-sql"&gt;sp_invoke_external_rest_endpoint&lt;/a&gt; stored procedure to &lt;a href="https://aka.ms/dab"&gt;Data API builder&lt;/a&gt; that takes your database and turn it into a stateless, scalable, REST and GraphQL API, through &lt;a href="https://learn.microsoft.com/en-us/sql/sql-server/what-s-new-in-sql-server-2022?view=sql-server-ver16&amp;amp;preserve-view=true#language"&gt;JSON improvements&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/en-us/sql/relational-databases/performance/optimized-locking?view=azuresqldb-current"&gt;optimized locking&lt;/a&gt; and more to come this year...so don't miss your chance to shape the future so that it will be as you want it to be!&lt;/p&gt;

&lt;p&gt;PS&lt;br&gt;
And of course I could I not mention also the Azure SQL database &lt;em&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/azure-sql/database/free-offer?view=azuresql"&gt;free tier&lt;/a&gt;&lt;/em&gt;? (And free in the sense of totally, completely free, with no time-limits!)&lt;/p&gt;

</description>
      <category>database</category>
      <category>development</category>
      <category>azure</category>
    </item>
    <item>
      <title>OpenAPI for your Azure SQL database</title>
      <dc:creator>Davide Mauri</dc:creator>
      <pubDate>Tue, 24 Oct 2023 22:20:27 +0000</pubDate>
      <link>https://dev.to/azure/openapi-for-your-azure-sql-database-58kk</link>
      <guid>https://dev.to/azure/openapi-for-your-azure-sql-database-58kk</guid>
      <description>&lt;p&gt;A recent and exciting feature of Data API builder (you may have learned about Data API builder from my previous article, as I used it to quickly make a stored procedure and a table available as REST endpoint to easily integrate with OpenAI) is the compatibility with OpenAPI specifications and Swagger. This was a highly demanded feature, and it is impressive to see it in action. You can quickly transform your database tables, views or stored procedures into standard, modern, scalable, REST endpoints that are accessible to everyone.&lt;/p&gt;

&lt;p&gt;For this example, in just a few minutes, I converted the AdventureWorksLT sample database into a REST service that you can access and use – yes, you heard me, enjoy it! – at this link: &lt;a href="https://dm-dab-awlt.azurewebsites.net/swagger"&gt;https://dm-dab-awlt.azurewebsites.net/swagger&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4gWE3NTQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i1deychli50ny7vxbw31.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4gWE3NTQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i1deychli50ny7vxbw31.png" alt="List of endpoints via Swagger" width="768" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The database can now be used easily with any modern frontend framework, be it React, Vue.JS, Svelte, Blazor or anything that is able to make a REST call, and easily query the data with a simple (just using plan Javascript here):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://dm-dab-awlt.azurewebsites.net/api/Customer/CustomerID/5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you also have pagination, sorting, filtering and field selection capabilities, not to mention support for authentication and authorization (in fact if you try to do anything other than a GET you’ll get a 403). Pretty impressive if you ask me!&lt;/p&gt;

&lt;p&gt;“Hold on a second!” – you might say – “I’ve just read recently somewhere that having all tables exposed is bad-bad-bad! Why are you doing this?”. I’m very familiar with that post that recently went viral, that really shows a nightmarish situation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DLC1FiA---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eu71dqnwb2p9x9tl7ta8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DLC1FiA---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eu71dqnwb2p9x9tl7ta8.png" alt="Tweet screenshot" width="761" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post highlights a crucial point: choose the appropriate tool for each task. Data manipulation should not be done inefficiently in the client or the backend. Let the database handle it. Relational databases (which nowadays always go beyond the relational model) can do the work for you in optimal ways. Azure SQL Database can do things that looks like magic to optimize data manipulation in ways you’ll never be able to do yourself (for example, figuring out in real time the best JOIN strategy via the newly introduced Adaptive Join feature), as it would be extremely expensive and absolutely impractical, to move all data out of the database and then do the join. Just ike the tweet says.&lt;/p&gt;

&lt;p&gt;Make sure that you do the right thing, and use views and stored procedure as needed, and expose those instead of all the tables. But as an example, having all the tables to play with is just fine for this playground, and allows you to get confident with Data API builder.&lt;/p&gt;

&lt;p&gt;If you want to install it in your own subscription, to play with the Data API builder configuration file and check out all the features we packed into Data API builder, here’s the GitHub repo with the deployment code that can help you to get started:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/azure-samples/dab-adventureworks-lt"&gt;https://github.com/azure-samples/dab-adventureworks-lt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, just have fun!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>database</category>
      <category>api</category>
      <category>azure</category>
    </item>
    <item>
      <title>How I built a session recommender in 1 hour using Open AI</title>
      <dc:creator>Davide Mauri</dc:creator>
      <pubDate>Wed, 18 Oct 2023 14:50:55 +0000</pubDate>
      <link>https://dev.to/azure/how-i-built-a-session-recommender-in-1-hour-using-open-ai-5419</link>
      <guid>https://dev.to/azure/how-i-built-a-session-recommender-in-1-hour-using-open-ai-5419</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcubl0tzr7m5balsf8dto.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcubl0tzr7m5balsf8dto.png" alt="Session Recommender Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a developer, I often attend conferences to learn new skills and network with other professionals. However, conferences can be overwhelming, especially when they offer dozens of sessions on different topics. How can I decide which ones are worth my time and attention?&lt;/p&gt;

&lt;p&gt;That's why I decided to use OpenAI to create a tool that can help me find the most relevant sessions for my interests. I used the session abstracts of a conference as input and converted them into embeddings using OpenAI's natural language processing capabilities. Then, I used vector search to compare the embeddings with a query topic and rank the sessions by similarity.&lt;/p&gt;

&lt;p&gt;This way, I can quickly and easily discover the sessions that match my goals and preferences, without having to read all the abstracts manually. I built this tool in a couple of hours during the weekend, using simple, scalable, and fast technologies.&lt;/p&gt;

&lt;p&gt;Here's how I did it. I hope you'll find it useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;The entire solution is a mix of fullstack, jamstack to be more precise, and event-driven architecture pattern.&lt;/p&gt;

&lt;p&gt;Sessions' data, which is structured by nature, is saved into a relational database and the tables and stored procedures are made available to the fronted via REST and GraphQL. &lt;/p&gt;

&lt;p&gt;Each time a new session is added, a serverless function is executed to turn abstracts into a vector by using OpenAI model via a REST call.&lt;/p&gt;

&lt;p&gt;A (minimal) web frontend allows end users to type a text that will also be converted into a vector using OpenAI and then the most similar vectors - and thus the associated sessions - will be found using cosine similarity.&lt;/p&gt;

&lt;p&gt;That's all. Simple, easy, elegant, and scalable: the architecture I love.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Floj4w53my53pm49d2zw3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Floj4w53my53pm49d2zw3.png" alt="Solution Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Details
&lt;/h2&gt;

&lt;p&gt;I used Azure for everything. Thanks to the various free and trial offers it is possible to create such a solution completely for free.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Frontend
&lt;/h3&gt;

&lt;p&gt;I used &lt;a href="https://learn.microsoft.com/en-us/azure/static-web-apps/overview" rel="noopener noreferrer"&gt;Azure Static Web Apps&lt;/a&gt; to host the fronted, written using React. Simple, well-known and easy to create. I'm new to React, so using this project was an effective way to ramp-up my skills while doing something funny and cool at the same time. I've learned a lot around the ecosystem around it (for example &lt;a href="https://reactrouter.com/en/main" rel="noopener noreferrer"&gt;react-router-dom&lt;/a&gt;, &lt;a href="//vite.js"&gt;vite&lt;/a&gt;) and the way it works internally.&lt;/p&gt;

&lt;p&gt;Azure Static Web Apps provides a fantastic on-prem development experience, and it is heavily integrated with GitHub, so that deployment is just a push to the target repository. Kind of obvious choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Backend
&lt;/h3&gt;

&lt;p&gt;Azure Static Web Apps comes with a cool feature named &lt;a href="https://learn.microsoft.com/en-us/azure/static-web-apps/database-overview" rel="noopener noreferrer"&gt;Database Connections&lt;/a&gt; that does a lot of heavy lifting for you. It automatically takes the database objects you configure and make them available via GraphQL and REST. &lt;/p&gt;

&lt;p&gt;Database Connections is powered by &lt;a href="https://aka.ms/dab" rel="noopener noreferrer"&gt;Data API builder&lt;/a&gt;, which is open-source and available also on-premises. It is heavily integrated with Static Web Apps, and the on-prem development experience that they provide is honestly unmatched. I was able to do everything on my machine with no friction at all, no CORS worries, authentication provider emulation, integration with vite tools...it is absolutely amazing! Same as for the frontend, the deployment to Azure is done via a simple &lt;em&gt;git push&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Database
&lt;/h3&gt;

&lt;p&gt;I used Azure SQL database. It now has a &lt;a href="https://devblogs.microsoft.com/azure-sql/new-azure-sql-database-free-offer/" rel="noopener noreferrer"&gt;free offer&lt;/a&gt;, and it can easily scale to terabytes of data if needed. Not that I think I need a terabyte of data for now...but you never know :)&lt;/p&gt;

&lt;h4&gt;
  
  
  About vectors
&lt;/h4&gt;

&lt;p&gt;Azure SQL database doesn't have a native vector type, but a vector is nothing more than a list of numbers. Relational databases are in general pretty good at managing list of things (otherwise known as sets 😊, otherwise known as &lt;em&gt;relations&lt;/em&gt; 😁) efficiently. &lt;/p&gt;

&lt;p&gt;With a dataset the size of the one I'm using, doing a full scan of all available vectors is desirable approach, as it performs &lt;em&gt;exact nearest neighbor&lt;/em&gt; search, which provides perfect &lt;a href="https://en.wikipedia.org/wiki/Precision_and_recall" rel="noopener noreferrer"&gt;recall&lt;/a&gt;. There is no need to specialized indexes, so Azure SQL looks like a great choice.&lt;/p&gt;

&lt;p&gt;In fact, even if the amount of data is not huge, is not insignificant either. OpenAI text embeddings return a vector with 1536 (float) values, so even with just 100 sessions to store the number of calculations to do in order to compute the cosine distance quickly approaches hundreds of thousands, and they should be done in the quickest way possible to accommodate as many requests per second as possible. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvpbqk0qoi3sct01uqyj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvpbqk0qoi3sct01uqyj.png" alt="Storing vectors in a table"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Azure SQL uses vector calculations internally (SIMD and AVX512 CPU instructions), to speed up operations on sets of data, and offers a columnstore index that can make operations on sets of data even faster. Not that a columnstore would be really needed for the small amount of data I have, but I wanted to give it a try to see how it would perform. And you'll see that the performances are great. The CPU usage is minuscule, and vector search is done in less than 50 msec on 100 of session abstracts. Impressive performance, and I don't have to install, manage, and integrate another database or a third-party library. Perfect: simplicity for the win! &lt;/p&gt;

&lt;p&gt;If you want to dig more into in doing vector search with Azure SQL, read the &lt;a href="https://devblogs.microsoft.com/azure-sql/vector-similarity-search-with-azure-sql-database-and-openai/" rel="noopener noreferrer"&gt;Vector Similarity Search with Azure SQL database and OpenAI&lt;/a&gt; article.  &lt;/p&gt;

&lt;h4&gt;
  
  
  OpenAI integration
&lt;/h4&gt;

&lt;p&gt;Finally, I wanted to keep the solution as simple as possible and as efficient as possible, so I wanted to use the new capability of Azure SQL to call a REST API directly to call OpenAI directly from inside the database to convert the searched text into a vector. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2uyrip3yba93sufb7954.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2uyrip3yba93sufb7954.png" alt="Call a REST service from Azure SQL DB"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By doing it inside the database, I don't have to create yet another Azure Function just for the purpose of calling the OpenAI REST endpoint and then storing the resulting vector in the database. This approach is something I can switch to in case I need more scalability, but there is no proof that such additional scalability is needed right now, so I decided to start with a simpler architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;The result is here for you to test out, which is something it will not only be interesting but also helpful if you plan to attend the &lt;a href="https://www.dotnetconf.net/" rel="noopener noreferrer"&gt;.NET Conf 2023&lt;/a&gt;. In fact, I populated the database of the published sample solution with their session abstracts. &lt;/p&gt;

&lt;p&gt;I spent more or less one hour building everything, mostly on React and the frontend side. Creating the database and publishing it as REST endpoint took probably no more than 10 minutes. 😍&lt;/p&gt;

&lt;p&gt;Try it out yourself here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aka.ms/dotnetconf2023-session-finder" rel="noopener noreferrer"&gt;https://aka.ms/dotnetconf2023-session-finder&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, the OpenAI calls are limited (I'm using the smallest tier) so you might see throttling happening. Please be patient or deploy everything in our subscription to try it out yourself, using the code available here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/azure-samples/azure-sql-db-session-recommender" rel="noopener noreferrer"&gt;https://github.com/azure-samples/azure-sql-db-session-recommender&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>database</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Vector Similarity Search with Azure SQL database and OpenAI</title>
      <dc:creator>Davide Mauri</dc:creator>
      <pubDate>Sun, 04 Jun 2023 20:47:36 +0000</pubDate>
      <link>https://dev.to/azure/vector-similarity-search-with-azure-sql-database-and-openai-147o</link>
      <guid>https://dev.to/azure/vector-similarity-search-with-azure-sql-database-and-openai-147o</guid>
      <description>&lt;p&gt;Vector databases are gaining quite a lot of interest lately. Using text embeddings and vector operations makes extremely easy to find similar "things". Things can be articles, photos, products…everything. As one can easily imagine, this ability is great to easily implement suggestions in applications. From providing suggestions on similar articles or other products that may be of interest, to quickly finding and grouping similar items, the applications are many.&lt;/p&gt;

&lt;p&gt;A great article to understand how embeddings work, is the following: &lt;a href="https://openai.com/blog/introducing-text-and-code-embeddings" rel="noopener noreferrer"&gt;Introducing text and code embeddings&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Reading the mentioned articles, you can learn that "embeddings are numerical representations of concepts converted to number sequences, which make it easy for computers to understand the relationships between those concepts."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4nibvrdorcj86x7nn8gu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4nibvrdorcj86x7nn8gu.png" alt="Text Embeddings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More specifically, embeddings are vectors…hence the great interest for vector databases.&lt;/p&gt;

&lt;p&gt;But are vector databases really needed? At the end of the day a vector is just a list of numbers and finding if two vectors represent similar object is as easy as calculating the distance between the vectors. One of the most common and useful distance metric is the &lt;a href="https://en.wikipedia.org/wiki/Cosine_similarity#Cosine_Distance" rel="noopener noreferrer"&gt;cosine distance&lt;/a&gt; and, even better, the related &lt;a href="https://en.wikipedia.org/wiki/Cosine_similarity/" rel="noopener noreferrer"&gt;cosine similarity&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnw42lxgcp3sw1zud9x0t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnw42lxgcp3sw1zud9x0t.png" alt="Cosine Distance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The real complex part is calculating the embeddings, but thanks to Azure OpenAI, everyone has an easily accessible REST service that can used to get the embeddings using pre-trained ML models. In this article we will use &lt;a href="https://learn.microsoft.com/en-us/azure/cognitive-services/openai/concepts/models#embeddings-models" rel="noopener noreferrer"&gt;OpenAI to generate vectors for doing similarity search&lt;/a&gt; and then use Azure SQL database to store and search for similar vectors.&lt;/p&gt;

&lt;p&gt;In this article we’ll build a sample solution to find Wikipedia articles that are related to any topic we may be interested in. As usual all the code is available in GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Azure-Samples/azure-sql-db-openai" rel="noopener noreferrer"&gt;https://github.com/Azure-Samples/azure-sql-db-openai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The pre-calculated embeddings, both for the title and the body, of a selection of Wikipedia articles, is made available by OpenAI here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cdn.openai.com/API/examples/data/vector_database_wikipedia_articles_embedded.zip" rel="noopener noreferrer"&gt;https://cdn.openai.com/API/examples/data/vector_database_wikipedia_articles_embedded.zip&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Vectors in Azure SQL database
&lt;/h2&gt;

&lt;p&gt;Vectors can be efficiently stored in Azure SQL database by &lt;a href="https://learn.microsoft.com/sql/relational-databases/indexes/columnstore-indexes-overview?view=sql-server-ver16" rel="noopener noreferrer"&gt;columnstore indexes&lt;/a&gt;. There is no specific data type available to store a vector in Azure SQL database, but we can use some human ingenuity to realize that a vector is just a list of numbers. As a result, we can store a vector in a table very easily by creating a column to contain vector data. One row per vector element. We can then use a columnstore index to efficiently store and search for vectors.&lt;/p&gt;

&lt;p&gt;Using this Wikipedia article as starting point, you can see that there are two vectors, one to store title embeddings and one to store article embeddings:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63hyfznkrcqu8fouooat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63hyfznkrcqu8fouooat.png" alt="Article with embeddings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The vectors can be more efficiently stored into a table like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;wikipedia_articles_embeddings_titles_vector&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;article_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;vector_value_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;vector_value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On that table we can create a column store index to efficiently store and search for vectors. Then it is just a matter of calculating the distance between vectors to find the closest. Thanks to the internal optimization of the columnstore (that uses &lt;a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data" rel="noopener noreferrer"&gt;SIMD&lt;/a&gt; &lt;a href="https://www.intel.com/content/www/us/en/architecture-and-technology/avx-512-overview.html" rel="noopener noreferrer"&gt;AVX-512 instructions &lt;/a&gt; to speed up vector operations) the distance calculation is extremely fast.&lt;/p&gt;

&lt;p&gt;The most common distance is the cosine similarity, which can be calculated quite easily in SQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Calculating cosine similarity
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Cosine_similarity" rel="noopener noreferrer"&gt;Cosine similarity&lt;/a&gt; can be calculated in SQL using the following formula, given two vectors a and b:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; 
    &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;  
        &lt;span class="n"&gt;SQRT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SQRT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;cosine_similarity&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
    &lt;span class="n"&gt;vectors_values&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Really easy. What is now left to do is to query the Azure OpenAI REST service so that, given any text, we can get the vector representation of that text. Then we can use that vector to calculate the cosine distance against all the Wikipedia articles stored in the database and take only the closest ones which will return the article most likely connect to the topic we are interested in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Querying OpenAI
&lt;/h2&gt;

&lt;p&gt;Create an Azure OpenAI resource via the Azure portal. For this specific sample you have to deploy an Embedding model using the &lt;code&gt;text-embedding-ada-002&lt;/code&gt; model, the same used for the Wikipedia articles source we are using in this sample. Once that is done, you need to get the API KEY and the URL of the deployed model (read the &lt;a href="https://learn.microsoft.com/azure/cognitive-services/openai/reference#embeddings" rel="noopener noreferrer"&gt;Embeddings REST API&lt;/a&gt; documentation) and then you can use &lt;a href="https://learn.microsoft.com/sql/relational-databases/system-stored-procedures/sp-invoke-external-rest-endpoint-transact-sql?view=azuresqldb-current" rel="noopener noreferrer"&gt;sp_invoke_external_rest_endpoint&lt;/a&gt; to call the REST API from Azure SQL database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;declare&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;retval&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="n"&gt;nvarchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;declare&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="n"&gt;nvarchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'input'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Isaac Asimov'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;exec&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;retval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sp_invoke_external_rest_endpoint&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'https://&amp;lt;your-app-name&amp;gt;.openai.azure.com/openai/deployments/&amp;lt;deployment-id&amp;gt;/embeddings?api-version=2023-03-15-preview'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'{"api-key":"&amp;lt;your api key&amp;gt;"}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;1536&lt;/span&gt; &lt;span class="n"&gt;elements&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;JSON&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Vector&lt;/span&gt; &lt;span class="k"&gt;values&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;easily&lt;/span&gt; &lt;span class="n"&gt;extracted&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="k"&gt;following&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;SQL&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;value_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openjson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'$.result.data[0].embedding'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Source code
&lt;/h2&gt;

&lt;p&gt;If you are interested in trying this amazing capability by yourself, you can find the source code here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Azure-Samples/azure-sql-db-openai" rel="noopener noreferrer"&gt;https://github.com/Azure-Samples/azure-sql-db-openai&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The provided sample is not optimized. For example, the square of the vectors: &lt;code&gt;SUM(a.value * a.value)&lt;/code&gt; could be pre-calculated and stored in a table for even better efficiency and performance. The sample is purposely simple to make it easier to understand the concept. Even if the sample is also not optimized for performance, it is still quite fast. On an eight vCore Azure SQL database, the query takes only half of a second to return the fifty most similar articles. The cosine distance is calculated on 25,000 articles, for a total of 38 million vector values. Pretty cool, fast and useful!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fianxmqkdi3e32k453iyj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fianxmqkdi3e32k453iyj.gif" alt="Returing the 50 most similar articles"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>ai</category>
      <category>database</category>
    </item>
    <item>
      <title>CTEs, Views or Temp Tables?</title>
      <dc:creator>Davide Mauri</dc:creator>
      <pubDate>Fri, 20 Jan 2023 18:03:38 +0000</pubDate>
      <link>https://dev.to/azure/ctes-views-or-temp-tables-340j</link>
      <guid>https://dev.to/azure/ctes-views-or-temp-tables-340j</guid>
      <description>&lt;p&gt;I've just finished watching the video from the &lt;a href="https://twitter.com/GuyInACube" rel="noopener noreferrer"&gt;@GuyInACube&lt;/a&gt; about Common Table Expressions&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/PsuxE6xExOw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;and I noticed that in several comments there was the request to explain what is the difference between Common Table Expressions, Views and Temp Tables.&lt;/p&gt;

&lt;p&gt;This is quite a common question, and it is time to give it a simple, concise, and clear answer, once and for all. &lt;/p&gt;

&lt;h2&gt;
  
  
  Common Table Expressions
&lt;/h2&gt;

&lt;p&gt;You can think of a &lt;a href="https://learn.microsoft.com/sql/t-sql/queries/with-common-table-expression-transact-sql" rel="noopener noreferrer"&gt;Common Table Expression (CTE)&lt;/a&gt; as a &lt;a href="https://learn.microsoft.com/sql/relational-databases/performance/subqueries" rel="noopener noreferrer"&gt;table subquery&lt;/a&gt;. A table subquery, also sometimes referred to as &lt;em&gt;derived table&lt;/em&gt;, is a query that is used as the starting point to build another query. Like a subquery, it will exist only for the duration of the query. CTEs make the code easier to write as you can write the CTEs at the top of your query - you can have more than one CTE, and CTEs can reference other CTEs - and then you can use the defined CTEs in your main query. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgtufff2f9an6phjle1co.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgtufff2f9an6phjle1co.png" alt="A sample of a CTE"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CTEs make the code easier to read, and favor reuse: imagine that in each CTE you are defining the subset of data that you want to work on in the main query and you are giving it a label. In the main query then you can just refer to that subset by using its label instead of having to write the whole subquery. &lt;/p&gt;

&lt;p&gt;CTEs also allows for some complex scenarios like &lt;a href="https://learn.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql?view=sql-server-ver16#guidelines-for-defining-and-using-recursive-common-table-expressions" rel="noopener noreferrer"&gt;recursive queries&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Views
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/sql/t-sql/statements/create-view-transact-sql" rel="noopener noreferrer"&gt;Views&lt;/a&gt; are metadata objects that allow to save the definition (and the definition only, not the result!) of a query and then use it later by referencing its name. To quote &lt;a href="https://www.amazon.com/Practical-Azure-Database-Modern-Developers/dp/1484263693" rel="noopener noreferrer"&gt;the book I wrote&lt;/a&gt; couple of years ago: "A view is nothing more than a query definition, labeled with name, and usable as a table. In fact, views are also known as &lt;em&gt;virtual tables&lt;/em&gt;, even if this name is seldomly used"&lt;/p&gt;

&lt;h2&gt;
  
  
  Temp Tables
&lt;/h2&gt;

&lt;p&gt;Temporary tables are regular tables that must start with &lt;code&gt;#&lt;/code&gt; character (or &lt;code&gt;##&lt;/code&gt; for global temporal tables), and on which the query engine can do some special optimization knowing they are ephemeral, that will be automatically dropped once going out of scope (for example, when the connection that created them is terminated).&lt;/p&gt;

&lt;p&gt;Temporary tables have no special relationships with queries: you can simply take any query result and save it into a temporary table using, for example, the &lt;a href="https://learn.microsoft.com/sql/t-sql/queries/select-into-clause-transact-sql" rel="noopener noreferrer"&gt;SELECT INTO&lt;/a&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fteyup635v3d7cq0qn300.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fteyup635v3d7cq0qn300.png" alt="SELECT INTO a temporary table"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the SELECT INTO command is finished, the relationship between the query that produced a result set and the temp table that has been used to store that result set is concluded. Think of it as a very simple ETL process. Once it is finished there is nothing that will automatically update or keep in sync the data in the temp table with the result set generated by the query used to move data into the temp table.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use what?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Let's start simple
&lt;/h3&gt;

&lt;p&gt;Let's say you have a complex query, where you must put together several different tables to produce the result set you need.&lt;/p&gt;

&lt;p&gt;👉 The first thing that is important to keep in mind, that Subqueries, Views and CTEs are all conceptually the same for the query engine. &lt;em&gt;SQL is declarative language where - unless there are some precedence constraints imposed by the operator used - everything is evaluated "all-at-once"&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;It means that there is no guarantee that a subquery (or a CTE or a view) will be executed before the query that uses it. &lt;/p&gt;

&lt;p&gt;This is a super important concept to grasp. It might sound strange to you, but this is a key feature of SQL as the query optimizer can decide - as long as the final result will be correct - to apply filters and optimization wherever is more appropriate.&lt;/p&gt;

&lt;p&gt;Let's say, for example, that you have a subquery that filters all people that live in Seattle. On this subquery you want to add an additional filter to limit the result set only to return people that are named Davide. &lt;/p&gt;

&lt;p&gt;👉 Thanks to the fact that SQL is "all-at-once" the optimizer can push the outer filter down to the inner subquery and immediately search for all those people who live in Seattle and are named Davide. &lt;/p&gt;

&lt;p&gt;If SQL hand't been "all-at-once", the database engine would have had to first execute the query and then search among the resulting rows for only those for which the name is Davide. &lt;/p&gt;

&lt;p&gt;That would have been an incredible waste of resources - more CPU and memory used - and would have provided a much worse performance result. &lt;/p&gt;

&lt;p&gt;In addition to that, it would also make index usage much more complex and less likely. If we had an index on the people's name, it would be useful only if we could filter first by name and then by city. Luckly the optimizer can move the filters around, given that the query simply states what you want and not how to get it. If we had, instead, to firstly execute the subquery and then the outer query, well...you can guess that the index wouldn't have been that useful, right?&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's complicate things a bit
&lt;/h3&gt;

&lt;p&gt;So far, from what has just been explained, it seems that using a subquery, a view, or CTE is always a clever idea as we're just allowing the query optimizer to do its work at best.&lt;/p&gt;

&lt;p&gt;On paper yes. In practice, we have to take into account that the query optimizer doesn't really know &lt;em&gt;exactly&lt;/em&gt; what values are contained in each table and how data is distributed. Does it have a normal distribution? Or is skewed toward some specific values?&lt;/p&gt;

&lt;p&gt;🚗 You can think of the query optimizer as your car navigation system.  When it plans for a route, it will do so considering the most up-to-date and accurate information about traffic...but you won't be 100% sure that the road it tells you to drive will be the best choice until you are there. What if there has been a sudden surge in traffic for whatever reason? Well, you're there now and you just must wait in queue (or take another road, of course).&lt;/p&gt;

&lt;p&gt;🙀 The database is similar in the sense that it will have statistical information of how data is distributed within a table. This is useful to try to decide the best strategy to return the data you're asking in the query, but it also comes with the fact that statistics come with a certain degree of error. This means that the query engine may estimate that the subquery will return "X" rows, but when it executes it will really return "Y" rows. If you have nested subqueries, the error will propagate and can get amplified, up to the point that - potentially - the query optimizer will try to use index "A" as it thinks at some point there will be only - for example - 10 rows involved, but there will be 10K for real, making the index usage a potentially bad choice.&lt;/p&gt;

&lt;p&gt;The amplitude of the error propagation and amplification is completely dependent on the query itself, the data in your tables and other factors (updates statics, partitions, etc.). The more table references you have, the more likely this is to happen. Imagine a complex query using CTEs calling several Views which have subqueries inside. Estimation errors will potentially pile up. &lt;/p&gt;

&lt;p&gt;How do you see if you are having estimation errors? &lt;a href="https://learn.microsoft.com/sql/relational-databases/performance/execution-plans" rel="noopener noreferrer"&gt;Execution Plans&lt;/a&gt; are your friend. They'll show what steps will be taken to generate the result set and for each step they will show the estimated and the current number of rows touched. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fol75q63n72avikfoe0gw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fol75q63n72avikfoe0gw.png" alt="Execution Plan showing estimated and actual rows"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you notice an estimation completely gone wrong (like several orders of magnitude differences) you may need to give the query optimizer some help.&lt;/p&gt;

&lt;h3&gt;
  
  
  Temporary tables to the rescue?
&lt;/h3&gt;

&lt;p&gt;Temporary tables can help to greatly reduce or even fix the poor row estimation due to the aforementioned error amplification. How? Well, by storing the result of a subquery into a temporary table, you are resetting such error amplification as the query engine can use the data in the temporary table and thus make sure it is not guessing too much anymore. &lt;/p&gt;

&lt;p&gt;Another reason to use a temporary table is if you have a complex query that needs to be used one or more time in subsequent steps and you want to avoid spending time and resource to execute that query again and again (especially if the result set is small compared to the originating data and/or the subsequent queries will not be able to push any optimization down to the subquery as you are working on aggregated data, for example)&lt;/p&gt;

&lt;p&gt;But there is no "one-solution-fits-all" here. You must try to see if, for your use case, a subquery is enough, or a temporary table is needed to give the query engine some leverage to get better estimations and thus a better execution plan.&lt;/p&gt;

&lt;p&gt;Keep also in mind that using temporary tables comes with some overhead. Aside from the obvious space usage, resources - and thus time - will be spent just for loading them. Sometimes you might even need to create indexes on temporary tables to make sure subsequent query performances are at the top. &lt;/p&gt;

&lt;p&gt;The data persisted in the temporary table, also, is not automatically kept up to date with any changes that might be made to the data in the tables used in the originating query. It is your responsibility to refresh the data on the temporary table anytime you need it (Another option would be to use Indexed Views: see below for more details on this feature).&lt;/p&gt;

&lt;h2&gt;
  
  
  Other stuff that you may want to know
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Indexed Views
&lt;/h3&gt;

&lt;p&gt;A special kind of Views, the &lt;a href="https://learn.microsoft.com/sql/relational-databases/views/create-indexed-views" rel="noopener noreferrer"&gt;&lt;em&gt;Indexed Views&lt;/em&gt;&lt;/a&gt;, can be created so that the produced result is materialized and persisted into the database data file. With Indexed Views, the result doesn't need to be re-calculated every time, so they are great for improving read performances. In HTAP scenarios they can help to get a great performance boost. The database engine will also make sure that every time data in one of the based tables used in an Indexed View is updated, the persisted result is updated too, so that you always have fresh and updated values.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inline Table-Valued Functions (aka Parametrized Views)
&lt;/h3&gt;

&lt;p&gt;Sometimes you would like to have a View with parameters, to make it  easier to return just the subset of values you are interested in. In Azure SQL and SQL Server, you can create parametrized views. They fall (more correctly, IMHO) under the umbrella of "Functions", and specifically they can be created by using Inline Table-Valued Functions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8k4kvgc63nckwc2z1opb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8k4kvgc63nckwc2z1opb.png" alt="An Inline Table-Valued Function aka Parametrized View"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Now you should have a clear picture of what is the difference between CTEs (or subqueries), Views and Temp Tables. &lt;/p&gt;

&lt;p&gt;My recommendation is to start with a CTE and then use temporary tables as needed, so that you can get the performance you want with the minimum overhead possible. (I like to say that usage of temporary table is like salt with foods. You can always add it later.)&lt;/p&gt;

&lt;p&gt;If you still have questions, make sure to leave them in the comments, so that we can keep the discussion on!&lt;/p&gt;




&lt;p&gt;Photo by &lt;a href="https://www.pexels.com/photo/architecture-black-and-white-challenge-chance-277593/" rel="noopener noreferrer"&gt;Pixabay from Pexels&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>database</category>
    </item>
    <item>
      <title>Advent of Code - Day 10</title>
      <dc:creator>Davide Mauri</dc:creator>
      <pubDate>Sun, 11 Dec 2022 04:39:18 +0000</pubDate>
      <link>https://dev.to/azure/advent-of-code-day-10-4n71</link>
      <guid>https://dev.to/azure/advent-of-code-day-10-4n71</guid>
      <description>&lt;p&gt;Last week I've been to the &lt;a href="https://www.devintersection.com/#!/" rel="noopener noreferrer"&gt;DevIntersection&lt;/a&gt; conference to present several sessions around Azure SQL and development (&lt;a href="https://www.devintersection.com/#!/session/Modern%20Architecture%20Patterns%20with%20Azure%20SQL%20Database/5712" rel="noopener noreferrer"&gt;Modern Architecture Patterns with Azure SQL Database&lt;/a&gt;, &lt;a href="https://www.devintersection.com/#!/session/The%2010%20things%20every%20developer%20must%20absolutely%20know%20about%20Azure%20SQL/5454" rel="noopener noreferrer"&gt;The 10 things every developer must absolutely know about Azure SQL&lt;/a&gt; and &lt;a href="https://www.devintersection.com/#!/workshop/Build%20a%20Jamstack%20solution%20in%20a%20day/5509" rel="noopener noreferrer"&gt;Build a Jamstack solution in a day&lt;/a&gt;) so...yeah, I'm already falling behind with the challenges. Anyway. I'll try to catch up with the challenge I missed later.&lt;/p&gt;

&lt;p&gt;I've also started using some of the &lt;a href="https://learn.microsoft.com/en-us/sql/sql-server/what-s-new-in-sql-server-2022?view=sql-server-ver16#language" rel="noopener noreferrer"&gt;new or updated language elements introduced in SQL Server 2022&lt;/a&gt;, also available in Azure SQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://adventofcode.com/2022/day/10" rel="noopener noreferrer"&gt;Challenge 10&lt;/a&gt; can be solved using a non-equi join, so that each command provided as input will have exactly one line per cycle. Here's how I did it.&lt;/p&gt;

&lt;p&gt;After importing the input using the usual &lt;code&gt;STRING_SPLIT&lt;/code&gt; I have a table with one row per command:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F806ipyql6httcc9x49o1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F806ipyql6httcc9x49o1.png" alt="One row per command" width="682" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All commands operate only on the fictional variable &lt;code&gt;X&lt;/code&gt;, which the challenge said start being set to &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Using a running total, I can calculate cycle number at which each command is issued and what is the final value if &lt;code&gt;X&lt;/code&gt; once the command has completed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cycles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;ordinal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;end_cycle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;isnull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;ordinal&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;end_value&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;commands&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On that resultset, using the &lt;code&gt;LAG&lt;/code&gt; operator, I can identify what is the value at the start and during the command execution, and what is the final value once the command is done. The challenge says, in fact, that the value of &lt;code&gt;X&lt;/code&gt; is changed only once the command is finished, not at the beginning or during the operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;lag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;end_cycle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;ordinal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;start_cycle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;end_cycle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;lag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;end_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;ordinal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;start_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;end_value&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is a table with all the data needed to resolve the challenge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq41jnldsjiyt8dykyhsq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq41jnldsjiyt8dykyhsq.png" alt="Added start and end cycle of command" width="800" height="66"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now I only have a &lt;em&gt;row per command&lt;/em&gt;, but instead I need a &lt;em&gt;row per cycle&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Not a big issue, since I have the start and end cycle of each command. I can generate a row per cycle by joining the one-row-per-command table with the usual numbers table (this time I'm using the new &lt;a href="https://learn.microsoft.com/en-us/sql/t-sql/functions/generate-series-transact-sql?view=sql-server-ver16" rel="noopener noreferrer"&gt;&lt;code&gt;GENERATE_SERIES&lt;/code&gt;&lt;/a&gt; introduced in SQL Server 2022 and available also on Azure SQL), I need to use a &lt;em&gt;non-equi join&lt;/em&gt; to generate as many rows as used cycles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;command_details&lt;/span&gt; &lt;span class="n"&gt;cd&lt;/span&gt;
&lt;span class="k"&gt;inner&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt;
     &lt;span class="n"&gt;generate_series&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_cycle&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end_cycle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I have one row per cycle:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0d7cq4zd2v3b58rckwx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0d7cq4zd2v3b58rckwx.png" alt="One row per cycle" width="800" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next step is a simple aggregation, filtering by the requested cycles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;select 
    sum([cycle] * [start_value]) as [signal_strength]
from
    #cycles_exploded
where 
    cycle in (20, 60, 100, 140, 180, 220)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Part 1 done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2
&lt;/h2&gt;

&lt;p&gt;Part 2 is very interesting, as the goal is to "visualize" the result of a fictional low-res CRT display. The display only has 40 rows and 6 columns. The first thing I had to do was to convert to &lt;code&gt;cycle&lt;/code&gt; value into horizontal and vertical coordinates. A division is enough to do the trick, and then I had to make sure that for each CRT line the leftmost position was set to 0, as explained in the challenge text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; 
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;cycle&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;row_number&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;partition&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;cycle&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt; &lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="k"&gt;cycle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;crt_pos&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;cycles_exploded&lt;/span&gt;
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then the only thing left to do is to implement the logic to understand what character will be printed on the CRT, as described in the challenge:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;iif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crt_pos&lt;/span&gt; &lt;span class="k"&gt;between&lt;/span&gt; &lt;span class="n"&gt;start_value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;start_value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'#'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;crt_char&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which will result in the following table:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5h85a697upm1qoj0bw4u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5h85a697upm1qoj0bw4u.png" alt="Rows with character to be displayed on the CRT" width="595" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and finally aggregate (making sure aggregation is done respecting the defined order, via the &lt;code&gt;WITHIN GROUP&lt;/code&gt; supported by &lt;a href="https://learn.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql?view=sql-server-ver16" rel="noopener noreferrer"&gt;&lt;code&gt;STRING_AGG&lt;/code&gt;&lt;/a&gt;) the characters values into a string so that the solution can appear. Part 2 solved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;The solution as usual is on GitHub: &lt;a href="https://github.com/yorek/aoc-2022/tree/main/day-10" rel="noopener noreferrer"&gt;https://github.com/yorek/aoc-2022/tree/main/day-10&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
    </item>
    <item>
      <title>Advent of Code - Day 4</title>
      <dc:creator>Davide Mauri</dc:creator>
      <pubDate>Mon, 05 Dec 2022 02:59:35 +0000</pubDate>
      <link>https://dev.to/azure/advent-of-code-day-4-5fg3</link>
      <guid>https://dev.to/azure/advent-of-code-day-4-5fg3</guid>
      <description>&lt;p&gt;&lt;a href="https://adventofcode.com/2022/day/4"&gt;Day 4 - Camp Cleanup&lt;/a&gt; challenge is all about dealing with intervals. Intervals are trickier and more complex than one might think. No surprise the organizer of the Advent Of Code, included them in their challenges.&lt;/p&gt;

&lt;p&gt;I did a lot of research on intervals, and specifically &lt;em&gt;time intervals&lt;/em&gt; in the past, with a specific focus on how they can be applied to Business Intelligence and more specifically to Fact Table. Couple of slide decks I created lately on the subject are the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.slideshare.net/davidemauri/temporal-snapshot-fact-tables"&gt;Temporal Snapshot Fact Tables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.slideshare.net/davidemauri/sql-server-2016-temporal-tables"&gt;SQL Server 2016 Temporal Tables&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As usual I'm importing the input data and storing it into a table. Input data contains &lt;em&gt;pairs&lt;/em&gt; of intervals, so I'm splitting the pairs and the interval begin and end into dedicated columns, for easier manipulation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ch04_input&lt;/span&gt; 
&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="k"&gt;identity&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="k"&gt;primary&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pair1_b&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pair1_e&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pair2_b&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pair2_e&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;cteLines&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;select&lt;/span&gt; 
        &lt;span class="k"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;from&lt;/span&gt;
        &lt;span class="n"&gt;string_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="n"&gt;ctePairs&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;select&lt;/span&gt; 
        &lt;span class="k"&gt;left&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;charindex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pair1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;charindex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pair2&lt;/span&gt;
    &lt;span class="k"&gt;from&lt;/span&gt;
        &lt;span class="n"&gt;cteLines&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; 
    &lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ch04_input&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pair1_b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pair1_e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pair2_b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pair2_e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt;
    &lt;span class="k"&gt;left&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;pair1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;charindex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pair1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pair1_b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;pair1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;pair1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;charindex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pair1&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pair1_e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;left&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;pair2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;charindex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pair2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pair2_b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;pair2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;pair2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;charindex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pair2&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pair2_e&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt;
    &lt;span class="n"&gt;ctePairs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the result is the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E_0GZ9w4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2nj05bmr1qh54cz7z81.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E_0GZ9w4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2nj05bmr1qh54cz7z81.png" alt="The input data split in begin and end points for each pair" width="547" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1
&lt;/h2&gt;

&lt;p&gt;The challenges ask to find all the pairs where one interval is completely included in the other. We must use the &lt;code&gt;CONTAINS&lt;/code&gt; operator that can be expressed using simple math:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l-O7SBhi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m6akxwprrkhpasurswzq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l-O7SBhi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m6akxwprrkhpasurswzq.png" alt="Math behind the CONTAINS operator" width="742" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;the query, therefore, is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;
    &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="k"&gt;from&lt;/span&gt; 
    &lt;span class="n"&gt;ch04_input&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pair1_b&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;pair2_b&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;pair1_e&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;pair2_e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;-- pair1 CONTAINS pair2&lt;/span&gt;
&lt;span class="k"&gt;or&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pair2_b&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;pair1_b&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;pair2_e&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;pair1_e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;-- pair2 CONTAINS pair1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Challenge solved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2
&lt;/h2&gt;

&lt;p&gt;The second challenge requires to find all the pairs in which interval overlaps. There's an operator for that, and the math is even simpler:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fLzpQYFK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqpyvyrcmva6sx7o8dd0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fLzpQYFK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqpyvyrcmva6sx7o8dd0.png" alt="Math behind the OVERLAPS operator" width="802" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The query then is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;
    &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; 
    &lt;span class="n"&gt;ch04_input&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pair1_b&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;pair2_e&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;pair2_b&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;pair1_e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;-- OVERLAPS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Challenge completed.&lt;/p&gt;

&lt;h2&gt;
  
  
  More content
&lt;/h2&gt;

&lt;p&gt;Three friends of mine, &lt;a href="https://www.linkedin.com/in/itzikbengan/"&gt;Itzik Ben-Gan&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/dejan-sarka-916641/"&gt;Dejan Sarka&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/adammachanic/"&gt;Adam Machanic&lt;/a&gt; were really passionate about this subject, and they shared a lot of content on the "interval" subject over the years.  As the internet continuously changes and evolves, it is not easy to find those articles. Since the challenge was quite quick to finish, I used some of the budgeted time to try to find the updated link to such content. Here you go:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.itprotoday.com/sql-server/interval-queries-sql-server"&gt;Interval Queries in SQL Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.itprotoday.com/sql-server/intervals-and-counts-part-1"&gt;Intervals and Counts, Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.itprotoday.com/sql-server/intervals-and-counts-part-2"&gt;Intervals and Counts, Part 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.itprotoday.com/development-techniques-and-management/intervals-and-counts-part-3"&gt;Intervals and Counts, Part 3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.itprotoday.com/sql-server/t-sql-interval-graphs-challenge-part-1"&gt;T-SQL Interval Graphs Challenge, Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.itprotoday.com/sql-server/t-sql-interval-graphs-challenge-part-2"&gt;T-SQL Interval Graphs Challenge, Part 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.itprotoday.com/development-techniques-and-management/tsql-challenge-packing-date-and-time-intervals"&gt;TSQL Challenge: Packing Date and Time Intervals&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And this is an entire session on a subject that is very much related with intervals&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://sqlbits.com/Sessions/Event17/Temporal_Data_in_SQL_Server"&gt;Temporal Data in SQL Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sqlbits.com/Sessions/Event12/Optimizing_Temporal_Queries"&gt;Optimizing Temporal Queries&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Incredibly, I haven't been able to find anything from Adam...it seems the collapse of SqlBlog.com resulted in a lot of lost knowledge :(. I've reached out to him; Here's couple of post that are still available on the subject:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://dataeducation.com/solving-the-net-changes-problem-with-temporal-tables-t-sql-tuesday-087/"&gt;Exploring “Fuzzy” Interval Islands Using SQLCLR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dataeducation.com/solving-the-net-changes-problem-with-temporal-tables-t-sql-tuesday-087/"&gt;Solving the Net Changes Problem with Temporal Tables&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sql</category>
      <category>programming</category>
      <category>beginners</category>
      <category>adventofcode</category>
    </item>
    <item>
      <title>Advent of Code - Day 3</title>
      <dc:creator>Davide Mauri</dc:creator>
      <pubDate>Sun, 04 Dec 2022 18:50:35 +0000</pubDate>
      <link>https://dev.to/azure/advent-of-code-day-3-5p2</link>
      <guid>https://dev.to/azure/advent-of-code-day-3-5p2</guid>
      <description>&lt;p&gt;Today's Advent of Code challenge is really interesting. Somehow easy, but with a couple of interesting discussion points.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://adventofcode.com/2022/day/3" rel="noopener noreferrer"&gt;Day 3: Rucksack Reorganization&lt;/a&gt; is about helping elves to organize and prioritize their supplies.&lt;/p&gt;

&lt;p&gt;I imported the input data as usual, by coping it from the website to my Azure Data Studio query and then using STRING_SPLIT to import each single line - that represents the rucksack content - in its own row:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;declare&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt; &lt;span class="n"&gt;nvarchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'QLFdFCdlLcVqdvFLnFLSSShZwptfHHhfZZZpSwfmHp
rTJRjjbJTgzDJjdsRsfwtfNwtfmZpZNhmmzt
...
jGrGqjJfqccrfqGcGplrJpFvzggqmCtMzmsMnvMvvCgm'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;drop&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;if&lt;/span&gt; &lt;span class="k"&gt;exists&lt;/span&gt; &lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ch03_input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;ch03_input&lt;/span&gt; 
&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="k"&gt;identity&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="k"&gt;primary&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;collate&lt;/span&gt; &lt;span class="n"&gt;Latin1_General_BIN2&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; 
    &lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ch03_input&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; 
    &lt;span class="k"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt;
    &lt;span class="n"&gt;string_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;go&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The items in the rucksacks are identified by a letter and the identifiers are case sensitive. For this reason, I used the &lt;code&gt;Latin1_General_BIN2&lt;/code&gt; collation that will make sure I adhere to the requirements and get the best performance possible with strings, as explained in Day 2 challenge solution post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1
&lt;/h2&gt;

&lt;p&gt;In the first part of the challenge, the rucksack list is split in two, and you must find the item type - represented by its letter - that is in both lists. It is a string comparison problem: which letter of the first list is &lt;em&gt;also&lt;/em&gt; in the second list?&lt;/p&gt;

&lt;p&gt;The first step is to split the list into two list of the same size:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; 
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;itemcount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;left&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;comp1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;comp2&lt;/span&gt;
&lt;span class="k"&gt;into&lt;/span&gt;    
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step1&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; 
    &lt;span class="n"&gt;ch03_input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also calculate the length of string as it will come useful in the next step, where I'll split the rucksack string into its letters and store each letter in its own row:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;row_number&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="k"&gt;cross&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="k"&gt;select&lt;/span&gt; 
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; 
&lt;span class="k"&gt;into&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step2&lt;/span&gt; 
&lt;span class="k"&gt;from&lt;/span&gt; 
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step1&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;  
&lt;span class="k"&gt;cross&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt; 
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;itemcount&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Splitting a string in its letters is easy if you have a table with numbers, which is what I'm creating as first thing in the query above. Then I use that numbers table to generate a row for each letter in the string, via the &lt;code&gt;CROSS JOIN&lt;/code&gt; and for each row generate extract the &lt;code&gt;Nth&lt;/code&gt; letter of the string. The &lt;code&gt;WHERE&lt;/code&gt; clause uses &lt;code&gt;itemcount&lt;/code&gt; to make sure that I generate exactly one row for each letter in each string, and no more than that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzv6imqltwf912zbc1wiw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzv6imqltwf912zbc1wiw.png" alt="The string split in its composing letters" width="427" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I need to find which item is in both compartments. This means checking if a letter is in a string and that can be done using &lt;a href="https://learn.microsoft.com/en-us/sql/t-sql/functions/charindex-transact-sql?view=sql-server-ver16" rel="noopener noreferrer"&gt;&lt;code&gt;CHARINDEX&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;distinct&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comp1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comp2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;charindex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comp1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;charindex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comp2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;p2&lt;/span&gt;
&lt;span class="k"&gt;into&lt;/span&gt; 
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step3&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; 
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step2&lt;/span&gt; 
&lt;span class="k"&gt;where&lt;/span&gt; 
    &lt;span class="n"&gt;charindex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comp1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; 
&lt;span class="k"&gt;and&lt;/span&gt; 
    &lt;span class="n"&gt;charindex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comp2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The query needs a &lt;code&gt;DISTINCT&lt;/code&gt; as there can be more than one item of the same type in the string, I need just only one per type. The fact that I need to use a &lt;code&gt;DISTINCT&lt;/code&gt; rings some bells (or bring some smell): I'm fairly sure I can refactor my code to do this operation earlier and avoid checking for a letter that has been found already. I'll do this later if I have enough free time. For now, I want to see if my solution works; after that I can optimize it.&lt;/p&gt;

&lt;p&gt;Now that the items present in both compartments have been found, I have to assign to each item type the priority value as described in the challenge. Priorities values are based on alphabetical order, so I can use &lt;a href="https://learn.microsoft.com/en-us/sql/t-sql/functions/ascii-transact-sql?view=sql-server-ver16" rel="noopener noreferrer"&gt;&lt;code&gt;ASCII&lt;/code&gt;&lt;/a&gt; to get the letter value and transform it to the corresponding priority value. Priority values are ordered differently than the ASCII order, so a &lt;code&gt;CASE&lt;/code&gt; statement is needed to apply the right transformations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;
    &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; 
        &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;like&lt;/span&gt; &lt;span class="s1"&gt;'[a-z]'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;ASCII&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;ASCII&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;like&lt;/span&gt; &lt;span class="s1"&gt;'[A-Z]'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;ASCII&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;ASCII&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;comp1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;comp2&lt;/span&gt;
&lt;span class="k"&gt;into&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;priorities&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step3&lt;/span&gt;
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt;
    &lt;span class="n"&gt;item&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now just summing all the priorities will give the answer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;priorities&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Answer is correct, so let's move to the next part of the challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2
&lt;/h2&gt;

&lt;p&gt;Elves gather in groups of three, and the goal is to find which item type is carried by everyone in the group.&lt;/p&gt;

&lt;p&gt;The first step is to create a way to easily group the elves together. By using the existing &lt;code&gt;id&lt;/code&gt; columns and the modulo operator I can find when a new group begins. When the result of the modulo operation is equal to one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9cpuz1irq04bk4xel076.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9cpuz1irq04bk4xel076.png" alt="Using modulo to identify groups" width="450" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I just need to know when a group starts, so I can set everything not equal to 1 to 0:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6urmpnjdrgmn7hclupu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6urmpnjdrgmn7hclupu.png" alt="First element in group is set to 1, others to 0" width="462" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now I can then use a simple and fast running total to generate a &lt;code&gt;group_id&lt;/code&gt; that will allow quick identification of all items in a single group. Amazing, isn't it?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzl4g2jvitqjl611rxga6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzl4g2jvitqjl611rxga6.png" alt="All elves in the same group have the same group id" width="477" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Funny enough my SQL Guru friend &lt;a href="https://sqlperformance.com/author/itzikbengan" rel="noopener noreferrer"&gt;Itzik&lt;/a&gt; mentioned this technique with the running total when we met yesterday evening. Funny that I would have needed it right the next day. Thanks Itzik!&lt;/p&gt;

&lt;p&gt;The final query is the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; 
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;itemcount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;group_id&lt;/span&gt;
&lt;span class="k"&gt;into&lt;/span&gt;    
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step1&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; 
    &lt;span class="n"&gt;ch03_input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;easy, fast, and elegant!&lt;/p&gt;

&lt;p&gt;Once that a way to identify each group is there, the challenge is almost solved. It is just a matter of splitting the strings into their letters, as I did for part one too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; 
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; 
&lt;span class="k"&gt;into&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step2&lt;/span&gt; 
&lt;span class="k"&gt;from&lt;/span&gt; 
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step1&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;  
&lt;span class="k"&gt;cross&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt; 
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;itemcount&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I have everything I need to see which letter is present in all three rucksacks. As simple &lt;code&gt;GROUP BY&lt;/code&gt; filtering only those letters that appears exactly three times by using the &lt;code&gt;HAVING&lt;/code&gt; clause will give the answer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;cte&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;    
    &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;distinct&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step2&lt;/span&gt; 
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt;
    &lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;item&lt;/span&gt;
&lt;span class="k"&gt;into&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step3&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt;
    &lt;span class="n"&gt;cte&lt;/span&gt;
&lt;span class="k"&gt;group&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; 
    &lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;
&lt;span class="k"&gt;having&lt;/span&gt;
    &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt;
    &lt;span class="n"&gt;group_id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tricky part here is the &lt;code&gt;DISTINCT&lt;/code&gt; operator in the &lt;a href="https://learn.microsoft.com/sql/t-sql/queries/with-common-table-expression-transact-sql?view=sql-server-ver16" rel="noopener noreferrer"&gt;Common Table Expression&lt;/a&gt;. That &lt;code&gt;DISTINCT&lt;/code&gt; makes sure I can differentiate between an item appearing three times in the same rucksack vs an item appearing one item in all three rucksacks. We're interested only in the latter, and not in the first.&lt;/p&gt;

&lt;p&gt;Now I just have to apply the same logic to get the priority value used before, calculate the overall total and I'll get the solution to Part 2. Challenge done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;The full solution is available here: &lt;a href="https://github.com/yorek/aoc-2022/tree/main/day-03" rel="noopener noreferrer"&gt;yorek/aoc-2022&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The technique to deal with &lt;em&gt;islands&lt;/em&gt; of data is useful in so many practical uses case that I really recommend you to deep dive into it. Take advantage of the free book chapter on the subject available here: &lt;a href="https://manning-content.s3.amazonaws.com/download/3/e589652-7171-4310-a714-e84dd0f14090/SampleChapter5.pdf" rel="noopener noreferrer"&gt;Gaps and islands&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternative solution to Part 2
&lt;/h2&gt;

&lt;p&gt;An alternative solution could have been a simple JOIN between the three rucksacks in the same group:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;distinct&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;
&lt;span class="k"&gt;into&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step3&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; 
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step2&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; 
&lt;span class="k"&gt;inner&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step2&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;
&lt;span class="k"&gt;inner&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;step2&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;go&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That would work just fine, but it will only work for a group of exactly three elves. While perfectly fitting the requirement, I find the chosen solution gives more flexibility and is way more elegant and future proof. Or &lt;em&gt;agile&lt;/em&gt; if you wish. It requires a  bit of &lt;a href="https://en.wikipedia.org/wiki/Lateral_thinking" rel="noopener noreferrer"&gt;&lt;em&gt;lateral thinking&lt;/em&gt;&lt;/a&gt;, which is always a good ability to exercise, so great to have a chance to use it. Given that the resulting query touches the table only once instead of, I also suspect it will also be faster. It is worth digging into it a bit more if you have time. &lt;/p&gt;

&lt;p&gt;Have fun!&lt;/p&gt;

</description>
      <category>career</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Advent of Code - Day 2</title>
      <dc:creator>Davide Mauri</dc:creator>
      <pubDate>Fri, 02 Dec 2022 21:51:31 +0000</pubDate>
      <link>https://dev.to/azure/advent-of-code-day-2-1fb2</link>
      <guid>https://dev.to/azure/advent-of-code-day-2-1fb2</guid>
      <description>&lt;p&gt;The &lt;a href="https://adventofcode.com/2022/day/2"&gt;second challenge&lt;/a&gt; of the &lt;a href="https://adventofcode.com"&gt;Advent of Code 2022&lt;/a&gt; is pretty straightforward with SQL. In summary the task is to use some starting values and transform those into a numeric value using a lookup table, and then calculate the sum of all the values you get. If you are familiar with relational databases this should sound like a &lt;a href="https://learn.microsoft.com/sql/relational-databases/performance/joins?view=sql-server-ver16"&gt;&lt;code&gt;JOIN&lt;/code&gt;&lt;/a&gt; operation to get the lookup value and a &lt;a href="https://learn.microsoft.com/sql/t-sql/queries/select-group-by-transact-sql?view=sql-server-ver16"&gt;&lt;code&gt;GROUP BY&lt;/code&gt;&lt;/a&gt; to get the results. &lt;/p&gt;

&lt;p&gt;The background story is that you are playing Tic-Tac-Toe with the elves. You are given an &lt;em&gt;encrypted strategy guide&lt;/em&gt; that you have to follow if you want to win.&lt;/p&gt;

&lt;p&gt;Let's start importing the input. As yesterday I've pasted the input  values in a query and then I'm using &lt;a href="https://learn.microsoft.com/sql/t-sql/functions/string-split-transact-sql?view=sql-server-ver16"&gt;&lt;code&gt;STRING_SPLIT&lt;/code&gt;&lt;/a&gt; to move everything into a more comfortable table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;declare&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'B Y
A Y
B Z
...
A Y'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;drop&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;if&lt;/span&gt; &lt;span class="k"&gt;exists&lt;/span&gt; &lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ch02_input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;cte&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;round&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;string_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; 
    &lt;span class="k"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;left&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;round&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;opponent&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
    &lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;round&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
&lt;span class="k"&gt;into&lt;/span&gt; 
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ch02_input&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cte&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full script is available on GitHub here: &lt;a href="https://github.com/yorek/aoc-2022/blob/main/day-02/00-setup.sql"&gt;day-02/00-setup.sql&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1
&lt;/h2&gt;

&lt;p&gt;In part one you have to assign to each shape a value. I built the set on the fly using the &lt;a href="https://learn.microsoft.com/en-us/sql/t-sql/queries/table-value-constructor-transact-sql?view=sql-server-ver16"&gt;Row Constructors&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; 
        &lt;span class="o"&gt;*&lt;/span&gt; 
&lt;span class="k"&gt;from&lt;/span&gt; 
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;values&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Rock'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Y'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Paper'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'B'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Paper'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'X'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Rock'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'C'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Scissors'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Z'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Scissors'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;        
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then all I had to do was join the above set with the input table, to convert the shapes into the associated value. I stored the result into the &lt;code&gt;#result&lt;/code&gt; temporary table.&lt;/p&gt;

&lt;p&gt;The last step to complete the task is to calculate if I won, tied, or lost each round. While I'm sure there are better ways to do that, given that the number of combinations is extremely limited, I went for a super simple solution, using the &lt;a href="https://learn.microsoft.com/sql/t-sql/language-elements/case-transact-sql?view=sql-server-ver16"&gt;&lt;code&gt;CASE&lt;/code&gt;&lt;/a&gt; statement (I'm really all in for &lt;a href="https://en.wikipedia.org/wiki/KISS_principle"&gt;KISS&lt;/a&gt; approach):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; 
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; 
        &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;opponent_shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;player_shape&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="c1"&gt;-- Tie&lt;/span&gt;
        &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;opponent_shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Rock'&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;player_shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Paper'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="c1"&gt;-- Won&lt;/span&gt;
        &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;opponent_shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Rock'&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;player_shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Scissors'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="c1"&gt;-- Lost&lt;/span&gt;
        &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;opponent_shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Paper'&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;player_shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Rock'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;-- Lost&lt;/span&gt;
        &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;opponent_shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Paper'&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;player_shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Scissors'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;  &lt;span class="c1"&gt;-- Won&lt;/span&gt;
        &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;opponent_shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Scissors'&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;player_shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Paper'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;-- Lost&lt;/span&gt;
        &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;opponent_shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Scissors'&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;player_shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Rock'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="c1"&gt;-- Won&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; 
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;rounds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, to calculate the overall score I did I just need to sum all my games:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;player_value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Part 1, done. Find the full script here: &lt;a href="https://github.com/yorek/aoc-2022/blob/main/day-02/01-part1.sql"&gt;day-02/01-part1.sql&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2
&lt;/h2&gt;

&lt;p&gt;In part two you discover that you didn't really decoded the original encrypted strategy guide. If fact, the X, Y and Z letter tells you not which shape you should play, but what should be the outcome of that game: "X means you need to lose, Y means you need to end the round in a draw, and Z means you need to win."&lt;/p&gt;

&lt;p&gt;To solve the challenge then, I only needed to transform the X, Y and Z into the related A, B and C, based on the given logic. Again, with a CASE statement is pretty easy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; 
    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="k"&gt;case&lt;/span&gt;
        &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Y'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;opponent&lt;/span&gt; &lt;span class="c1"&gt;-- Must tie&lt;/span&gt;
        &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'X'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="c1"&gt;-- Must lose&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;opponent&lt;/span&gt;
                &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'A'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="s1"&gt;'C'&lt;/span&gt;
                &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'B'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="s1"&gt;'A'&lt;/span&gt;
                &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'C'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="s1"&gt;'B'&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Z'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="c1"&gt;-- Must win&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;opponent&lt;/span&gt; 
                &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'A'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="s1"&gt;'B'&lt;/span&gt;
                &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'B'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="s1"&gt;'C'&lt;/span&gt;
                &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'C'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="s1"&gt;'A'&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;player_decoded&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; 
    &lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ch02_input&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;eg&lt;/span&gt;
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt;
    &lt;span class="n"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these results I can just then apply the same queries used in Part One to calculate the round results and then get the overall result points. The full script for part two is here: &lt;a href="https://github.com/yorek/aoc-2022/blob/main/day-02/02-part2.sql"&gt;day-02/02-part2.sql&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional notes
&lt;/h2&gt;

&lt;p&gt;With such small datasets performances are almost never an issue. If you were to use a much larger dataset, say 100 times bigger than this, I would suggest three things to make sure you'll get the best performances possible&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you can, use numbers - integers - as identifiers. Those are much faster when aggregations are required. Strings are &lt;em&gt;really&lt;/em&gt; expensive from a CPU perspective. &lt;/li&gt;
&lt;li&gt;If you cannot use numbers as identifiers for any reason, make sure you create columns or operate on string using a &lt;em&gt;binary&lt;/em&gt; collation. That will make string comparisons (and thus aggregations) much faster as the engine doesn't have to take into account casing, accents and so on. A collation like &lt;code&gt;Latin1_General_BIN2&lt;/code&gt; is your friend when a string is used as id. (&lt;a href="https://learn.microsoft.com/sql/relational-databases/collations/collation-and-unicode-support?view=sql-server-ver16#Binary-collations"&gt;Binary Collations&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/sql/relational-databases/collations/collation-and-unicode-support?view=sql-server-ver16#Column-level-collations"&gt;Colummn-level Collations&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/sql/relational-databases/collations/collation-and-unicode-support?view=sql-server-ver16#Expression-level-collations"&gt;Expression-level Collations&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Use the &lt;a href="https://learn.microsoft.com/ql/relational-databases/indexes/columnstore-indexes-overview?view=sql-server-ver16"&gt;columnstore indexes&lt;/a&gt; whenever you need to boost the aggregation performance. &lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>sql</category>
      <category>beginners</category>
      <category>programming</category>
      <category>adventofcode</category>
    </item>
    <item>
      <title>Advent of Code - Day 1</title>
      <dc:creator>Davide Mauri</dc:creator>
      <pubDate>Thu, 01 Dec 2022 23:51:00 +0000</pubDate>
      <link>https://dev.to/azure/advent-of-code-day-1-hig</link>
      <guid>https://dev.to/azure/advent-of-code-day-1-hig</guid>
      <description>&lt;p&gt;The &lt;a href="https://adventofcode.com/2022/day/1" rel="noopener noreferrer"&gt;first challenge&lt;/a&gt; of the &lt;a href="https://adventofcode.com" rel="noopener noreferrer"&gt;Advent of Code 2022&lt;/a&gt; is out, and this year I decided to try to solve the proposed challenges only using T-SQL. I also want to share the solutions here, as I think they will provide a great learning experience for those who are new to SQL, and get a sense of how powerful it is. Here's the solution to the first one (I'll try to keep up with the challenges every day, but I really can't promise anything as it really depends on how much free time I'll have after work and family needs...)&lt;/p&gt;

&lt;p&gt;The problem is about elves (of course!), food and calories. You start with a list of calories that elves are bringing with them. The list you are given as the starting point of this challenge has empty lines to separate the calories of each elf in their own inventory. Here's an example, simplified and moved to a spreadsheet for easier understanding:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ypbvwn8vdhcgbn5hiw7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ypbvwn8vdhcgbn5hiw7.png" alt="Sample starting data"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's start importing the calories data. I just pasted the content from the Advent of Code website and the used the &lt;a href="https://learn.microsoft.com/sql/t-sql/functions/string-split-transact-sql" rel="noopener noreferrer"&gt;&lt;code&gt;STRING_SPLIT&lt;/code&gt;&lt;/a&gt; function to turn the string into a table and then move the data into the final table I'll be using for this challenge:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;drop&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;if&lt;/span&gt; &lt;span class="k"&gt;exists&lt;/span&gt; &lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ch01_input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ch01_input&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="k"&gt;identity&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="k"&gt;primary&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;calories&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;go&lt;/span&gt;

&lt;span class="k"&gt;declare&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;calories&lt;/span&gt; &lt;span class="n"&gt;nvarchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'
3264
4043

...&amp;lt;content from the Advent of Code file here&amp;gt;...

6438
1020'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; 
    &lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ch01_input&lt;/span&gt; 
&lt;span class="k"&gt;select&lt;/span&gt; 
    &lt;span class="k"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nullif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;calories&lt;/span&gt; 
&lt;span class="k"&gt;from&lt;/span&gt; 
    &lt;span class="n"&gt;string_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;calories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;go&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, I'm also converting the empty lines into &lt;code&gt;NULL&lt;/code&gt; values, so that they can fit into a &lt;code&gt;INT&lt;/code&gt; data type as calories values are just numbers. Choosing the right data type is good for data hygiene and to avoid expensive cast operations in future. Strings requires quite a lot of CPU power compared to numbers, and on the cloud, since your pay for what you use, you really want to optimize performances to reduce costs. Not that in this case it would matter as there are just a few thousand rows, but it is nonetheless a good habit to have. I do not want to overengineer, but just some common sense is always good to apply.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1
&lt;/h2&gt;

&lt;p&gt;The first challenge is to "Find the Elf carrying the most Calories. How many total Calories is that Elf carrying?"&lt;/p&gt;

&lt;p&gt;That is easy! From the spreadsheet you can &lt;em&gt;see&lt;/em&gt; that each elf has a nice set of values, so the problem can be easily solved if we could find a way to easily identify and work on these sets of  values. In fact, as per challenge description: "Each Elf separates their own inventory from the previous Elf's inventory (if any) by a blank line". Too bad there are two thousand values so we can't do it visually. The first solution that can come to mind is to just start from the first row and process all of them in sequence, assigning the calories values to a new elf whenever a white line is found. That would work, but it just feels like a "brute force approach". We can do better: we can be &lt;em&gt;smart&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We can use some simple math to identify all the sets of values in the provided list. All that is needed is to give each row a sequential number based on its ordinal position in the file, including the blank lines, and another sequential number excluding, this second time, the blank rows. Here's an example using the simplified spreadsheet representation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjzai6mpxydstbxv71f73.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjzai6mpxydstbxv71f73.png" alt="Added two ordinals to the initial data set"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;N1&lt;/em&gt; and &lt;em&gt;N2&lt;/em&gt; represent the ordinals given to each element, based on its order, as mentioned before.&lt;/p&gt;

&lt;p&gt;Now, if you subtract the values in N2 from the values in N1, you'll get a &lt;strong&gt;group identifier&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqr79m7ctdc0m1pf7lss.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqr79m7ctdc0m1pf7lss.png" alt="Group identifiers shown"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Isn't that cool! In T-SQL this can be done easily, thanks to the &lt;a href="https://learn.microsoft.com/sql/t-sql/functions/row-number-transact-sql" rel="noopener noreferrer"&gt;&lt;code&gt;row_number()&lt;/code&gt;&lt;/a&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;drop&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;if&lt;/span&gt; &lt;span class="k"&gt;exists&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;part1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; 
    &lt;span class="n"&gt;group_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;row_number&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt; 
&lt;span class="k"&gt;into&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;part1&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; 
    &lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ch01_input&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;calories&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that &lt;code&gt;#part1&lt;/code&gt; contains the data with also the group identifier, a &lt;code&gt;group by&lt;/code&gt; can give the answer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;totcalories&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;part1&lt;/span&gt;
&lt;span class="k"&gt;group&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt;
    &lt;span class="n"&gt;group_id&lt;/span&gt;
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt;
    &lt;span class="n"&gt;totcalories&lt;/span&gt; &lt;span class="k"&gt;desc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 2
&lt;/h2&gt;

&lt;p&gt;Once the first part of the challenge is done, you'll have access to the second part. The question this time is: "Find the top three Elves carrying the most Calories. How many Calories are those Elves carrying in total?"&lt;/p&gt;

&lt;p&gt;Again, pretty easy now that we have a group identifier. We just must take the top three and sum them up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;cte&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;totcalories&lt;/span&gt;
    &lt;span class="k"&gt;from&lt;/span&gt;
        &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;part1&lt;/span&gt;
    &lt;span class="k"&gt;group&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt;
        &lt;span class="n"&gt;group_id&lt;/span&gt;
    &lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt;
        &lt;span class="n"&gt;totcalories&lt;/span&gt; &lt;span class="k"&gt;desc&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totcalories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;totaltop3&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cte&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done!&lt;/p&gt;

&lt;h2&gt;
  
  
  Gaps and Islands
&lt;/h2&gt;

&lt;p&gt;The technique used to solve this problem is well known and my friend and SQL Guru Itzik Ben-Gan has some great articles on it and how it can be used to solve complex problems. Here's some references for you do dig into it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://manning-content.s3.amazonaws.com/download/3/e589652-7171-4310-a714-e84dd0f14090/SampleChapter5.pdf" rel="noopener noreferrer"&gt;Gaps and islands&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.itprotoday.com/sql-server/solving-gaps-and-islands-enhanced-window-functions" rel="noopener noreferrer"&gt;Solving Gaps and Islands with Enhanced Window Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sqlperformance.com/?s=islands" rel="noopener noreferrer"&gt;Articles on sqlperformance.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sql</category>
      <category>beginners</category>
      <category>programming</category>
      <category>adventofcode</category>
    </item>
    <item>
      <title>Push the data out</title>
      <dc:creator>Davide Mauri</dc:creator>
      <pubDate>Tue, 22 Nov 2022 17:34:16 +0000</pubDate>
      <link>https://dev.to/azure/push-the-data-out-53j9</link>
      <guid>https://dev.to/azure/push-the-data-out-53j9</guid>
      <description>&lt;p&gt;Event-Driven and reactive architectures (see the &lt;a href="https://www.reactivemanifesto.org/"&gt;"Reactive Manifesto"&lt;/a&gt; if you're new to the topic or interested to learn more about it) are very popular today. Events - and thus data - is pushed to services so that integration can happen faster and more efficiently.&lt;/p&gt;

&lt;p&gt;With Azure SQL database it is possible to call a REST API using the stored procedure &lt;code&gt;sp_invoke_external_rest_endpoint&lt;/code&gt;. It is available in any Azure SQL Database (so, no Azure SQL Managed Instance or SQL Server for now) and it as easy to use as you would expect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;declare&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="n"&gt;nvarchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;sp_invoke_external_rest_endpoint&lt;/span&gt; 
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="s1"&gt;'https://say-hello.azurewebsites.net/api/hello-message'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openjson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take a look at the documentation here: &lt;a href="https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-invoke-external-rest-endpoint-transact-sql"&gt;sp_invoke_external_rest_endpoint (Transact-SQL)&lt;/a&gt; and unleash your creativity. The possibilities that this feature opens are almost infinite.&lt;/p&gt;

&lt;p&gt;The feature is in Public Preview, which means that this is the perfect time to give us your feedback, if you think something can be improved or needs to be changed. Feel free to comment here below, if you have any questions or ideas you want to share.&lt;/p&gt;

&lt;p&gt;In the meantime, happy coding! :)&lt;/p&gt;

</description>
      <category>azure</category>
      <category>eventdriven</category>
      <category>programming</category>
      <category>database</category>
    </item>
  </channel>
</rss>
