<?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: Chidiebere Ogujeiofor</title>
    <description>The latest articles on DEV Community by Chidiebere Ogujeiofor (@chidioguejiofor).</description>
    <link>https://dev.to/chidioguejiofor</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%2F274988%2F50ecdd87-e493-43bd-b86f-4b7fd3dfacd6.jpeg</url>
      <title>DEV Community: Chidiebere Ogujeiofor</title>
      <link>https://dev.to/chidioguejiofor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chidioguejiofor"/>
    <language>en</language>
    <item>
      <title>Scenario 2: Mastering Backfilling for New dB Columns – Update Like a Pro!</title>
      <dc:creator>Chidiebere Ogujeiofor</dc:creator>
      <pubDate>Wed, 25 Sep 2024 09:56:35 +0000</pubDate>
      <link>https://dev.to/chidioguejiofor/scenario-2-back-filling-data-of-a-new-column-3o05</link>
      <guid>https://dev.to/chidioguejiofor/scenario-2-back-filling-data-of-a-new-column-3o05</guid>
      <description>&lt;p&gt;Cover Photo Credit: &lt;a href="https://www.pexels.com/photo/person-holding-paint-roller-while-painting-the-wall-994164/" rel="noopener noreferrer"&gt;Pixels&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;One of the most interesting challenges I’ve encountered is when adding new fields to an existing database table and needing to back-fill values for those fields. Often, back-filling involves performing some sort of aggregation or calculation—sometimes involving other tables or columns—and then updating the target table with those calculated values.&lt;/p&gt;

&lt;p&gt;Let’s explore a concrete example using some sample data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem Example
&lt;/h3&gt;

&lt;p&gt;Imagine we decide to add two new fields to our events table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;number_of_ticket_types&lt;/code&gt;: This will hold the count of different ticket types associated with each event.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;number_of_tickets_available&lt;/code&gt;: This will represent the total number of tickets still available for the event, calculated as the sum of &lt;code&gt;ticket.quantity&lt;/code&gt; minus &lt;code&gt;ticket.quantity_sold&lt;/code&gt; for each event.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These fields can be useful if, for instance, you are retrieving a list of &lt;code&gt;events&lt;/code&gt; and need to display ticket information without requiring a user to click into the details of each event.&lt;/p&gt;

&lt;p&gt;We’ll start by adding a migration that adds these new columns to our &lt;code&gt;events&lt;/code&gt; table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Fields&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Constraints&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;owner_id&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;FK -&amp;gt; Users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;VARCHAR(30)&lt;/td&gt;
&lt;td&gt;PK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;number_of_ticket_types&lt;/td&gt;
&lt;td&gt;INT&lt;/td&gt;
&lt;td&gt;default:0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;number_of_tickets_available&lt;/td&gt;
&lt;td&gt;INT&lt;/td&gt;
&lt;td&gt;default:0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;However, when these new fields are added, their values will be set to 0 for all existing events, even though we already have tickets in the tickets table. Now, we need to backfill those fields with the correct data.&lt;/p&gt;

&lt;h3&gt;
  
  
  A First Attempt at Backfilling
&lt;/h3&gt;

&lt;p&gt;One way to backfill these new fields is to retrieve data from the tickets table, perform calculations, and then update the events table accordingly.&lt;/p&gt;

&lt;p&gt;Here’s an example of how to backfill the number_of_ticket_types field:&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;backFillTicketTypes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ticketTypeResult&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;TicketsModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;event_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;col&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ticket_type_count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tickets.event_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="cm"&gt;/*
    Result would look like this:
    ticketTypeResult = [ 
        {event_id: 'eventId1', ticket_type_count: 10},
        {event_id: 'eventId2', ticket_type_count: 4},
        {event_id: 'eventId3', ticket_type_count: 3},
    ]
  */&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;eventTicketTypeObject&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;ticketTypeResult&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;event_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ticket_type_count&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;eventTicketTypeObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;EventsModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;ticketTypeCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ticket_type_count&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="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event_id&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="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second field, &lt;code&gt;number_of_tickets_available&lt;/code&gt;, can be backfilled similarly by calculating the total available tickets:&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;backFillNumberOfTicketsAvailable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ticketsAvailableResult&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;TicketsModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;event_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sum&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;col&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;quantity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;total_tickets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sum&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;col&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;quantity_sold&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;total_tickets_sold&lt;/span&gt;&lt;span class="dl"&gt;"&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="na"&gt;group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tickets.event_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="cm"&gt;/*
    Result would look like this:
    ticketsAvailableResult = [ 
        {event_id: 'eventId1', total_tickets: 10, total_tickets_sold: 2},
        {event_id: 'eventId2', total_tickets: 23, total_tickets_sold: 12},
        {event_id: 'eventId3', total_tickets: 14, total_tickets_sold: 8},
    ]
  */&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numberOfTicketAvailable&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;ticketsAvailableResult&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;event_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;total_tickets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;total_tickets_sold&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="nx"&gt;numberOfTicketAvailable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;EventsModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;number_of_ticket_types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;total_tickets&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;total_tickets_sold&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="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event_id&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="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Run update query...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What's Wrong with This Approach?
&lt;/h3&gt;

&lt;p&gt;While this method works, it’s quite verbose and involves multiple database queries:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A query to retrieve ticket_type_count for each event.&lt;/li&gt;
&lt;li&gt;A query to retrieve total_tickets and total_tickets_sold for each event.&lt;/li&gt;
&lt;li&gt;An &lt;code&gt;UPDATE&lt;/code&gt; query for each event that has been created in the database. This is a really expensive task if many items have been created in the database previously&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the above example the total number of dB calls is dependent on the total number of events that exists in the application.&lt;/p&gt;

&lt;p&gt;Which would greatly slow down our server&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: If we use the techniques from the previous article(&lt;a href="https://dev.to/chidioguejiofor/scenario-1-making-updates-to-multiple-fields-56hl"&gt;Senerio 1&lt;/a&gt;), we would be able to reduce the number of &lt;code&gt;UPDATE&lt;/code&gt; query calls to 1 per function. Which would reduce the total queries to four&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  A Better Solution
&lt;/h3&gt;

&lt;p&gt;A more efficient way to handle this problem is to use a single SQL query to perform both updates in one go. We can achieve this using a WITH clause (common table expression, or &lt;a href="https://dev.to/chidioguejiofor/whats-with-cte-53ao"&gt;CTE&lt;/a&gt;) and a single UPDATE query.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To learn more about CTEs, check out [this article(&lt;a href="https://dev.to/chidioguejiofor/whats-with-cte-53ao)"&gt;https://dev.to/chidioguejiofor/whats-with-cte-53ao)&lt;/a&gt;]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s how we can do it:&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;update_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;event_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;COUNT&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="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;ticket_type_count&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;quantity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&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;quantity_sold&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;number_of_tickets_available&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt;
    &lt;span class="n"&gt;tickets&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;event_id&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt;
  &lt;span class="n"&gt;events&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt;
  &lt;span class="n"&gt;number_of_ticket_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update_cte&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ticket_type_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;number_of_tickets_available&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update_cte&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number_of_tickets_available&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="n"&gt;update_cte&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
  &lt;span class="n"&gt;update_cte&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;events&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;h3&gt;
  
  
  Explanation
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;WITH update_cte&lt;/code&gt; clause calculates both the &lt;code&gt;ticket_type_count&lt;/code&gt; and &lt;code&gt;number_of_tickets_available&lt;/code&gt; in one go using &lt;code&gt;COUNT&lt;/code&gt; and &lt;code&gt;SUM&lt;/code&gt; functions, grouped by &lt;code&gt;event_id&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;UPDATE&lt;/code&gt; statement, we join the events table with the CTE (&lt;code&gt;update_cte&lt;/code&gt;) based on event_id.&lt;/li&gt;
&lt;li&gt;The fields in events (&lt;code&gt;number_of_ticket_types&lt;/code&gt; and &lt;code&gt;number_of_tickets_available&lt;/code&gt;) are updated with the values from the CTE.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Why Is This Better?
&lt;/h3&gt;

&lt;p&gt;This approach performs both updates in a single query, eliminating the need for multiple database queries and significantly improving performance. Instead of managing two separate functions and multiple steps, we only need to maintain one query that efficiently backfills the data.&lt;/p&gt;

&lt;p&gt;Additionally, the same concept can be applied to future backfills if similar aggregate fields are added to the events table.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Backfilling data after adding new fields to an existing table is a common task in application development. While the initial approach of making multiple queries works, it can be optimized significantly using SQL’s powerful aggregation and CTE features. By consolidating updates into a single query, we reduce database load, improve performance, and make the code more maintainable.&lt;/p&gt;

</description>
      <category>sql</category>
      <category>typescript</category>
      <category>backenddevelopment</category>
      <category>performance</category>
    </item>
    <item>
      <title>Scenario 1: When You Need to Update Multiple Rows with Different Values – The Smart Way!</title>
      <dc:creator>Chidiebere Ogujeiofor</dc:creator>
      <pubDate>Tue, 24 Sep 2024 18:36:11 +0000</pubDate>
      <link>https://dev.to/chidioguejiofor/scenario-1-making-updates-to-multiple-fields-56hl</link>
      <guid>https://dev.to/chidioguejiofor/scenario-1-making-updates-to-multiple-fields-56hl</guid>
      <description>&lt;p&gt;Here's an improved version of the introduction for Scenario 1:&lt;/p&gt;

&lt;p&gt;Updating multiple rows in a database is a common task when managing data, whether you're setting the same value across several rows or handling different updates for each one. While the former is straightforward, the latter can quickly become complex and lead to performance issues due to excessive database calls.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore how to efficiently update multiple rows with different values in a single query to minimize database overhead and improve performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem Example
&lt;/h3&gt;

&lt;p&gt;Imagine you want event owners to update the prices of multiple tickets at once. The event owner provides an array of objects containing the ticket IDs and their new prices. The input might look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-event-conference-id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ticketUpdateArr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"id1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"newPrice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"id2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"newPrice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"id3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"newPrice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;790&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"id4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"newPrice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A straightforward implementation to handle this update might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bulkUpateTickets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ticketUpdateArr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateObj&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;ticketUpdateArr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;TicketsModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;updateObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newPrice&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="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;updateObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, we loop through each item in the array and make a separate database call to update the price for each ticket. &lt;/p&gt;

&lt;p&gt;While this works, it’s not efficient. Each database call is expensive, and as the number of tickets grows, this function becomes significantly slower.&lt;/p&gt;

&lt;h4&gt;
  
  
  How Can We Improve This?
&lt;/h4&gt;

&lt;p&gt;We can improve performance by moving the logic to the database and utilizing SQL CASE statements. This allows us to update all tickets in a single query.&lt;/p&gt;

&lt;p&gt;Here’s how the query would look:&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;UPDATE&lt;/span&gt;
    &lt;span class="n"&gt;tickets&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'id1'&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'id2'&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;700&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'id3'&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;790&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'id4'&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;1500&lt;/span&gt;
        &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'id2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'id3'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'id4'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query updates all the ticket prices in one go. The parts that come from user input are the WHEN ... THEN conditions and the list of ids in the WHERE clause.&lt;/p&gt;

&lt;p&gt;Now, let's update our JavaScript code to dynamically build the query and make just one database call.&lt;/p&gt;

&lt;h3&gt;
  
  
  Improved JavaScript Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bulkUpdateTickets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ticketUpdateArr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ticketUpdateArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;caseStatement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ticketIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;replacements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;ticketUpdateArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;index&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ticketUpdateArr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ticketIdReplacement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`ticket_id_&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ticketValueReplacement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`ticket_value_&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;caseStatement&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="cm"&gt;/*sql*/&lt;/span&gt; &lt;span class="s2"&gt;`
      WHEN id = :&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ticketIdReplacement&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; THEN :&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ticketValueReplacement&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;replacements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ticketIdReplacement&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;updateObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;replacements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ticketValueReplacement&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;updateObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newPrice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;ticketIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rawQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="cm"&gt;/*sql*/&lt;/span&gt; &lt;span class="s2"&gt;`
    UPDATE
        tickets
    SET
        amount = CASE &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;caseStatement&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
        ELSE amount
    END
    WHERE id IN (:ticket_ids);
  `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rawQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;QueryTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;replacements&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="nx"&gt;replacements&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;ticket_ids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ticketIds&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="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code builds a dynamic SQL CASE statement based on the input array, constructing the WHEN ... THEN clauses and the list of ticket ids for the WHERE clause. Here's an example of the generated SQL:&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;UPDATE&lt;/span&gt;
    &lt;span class="n"&gt;tickets&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ticket_id_0&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ticket_value_0&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ticket_id_1&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ticket_value_1&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ticket_id_2&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ticket_value_2&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ticket_id_3&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ticket_value_3&lt;/span&gt;
        &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;ticket_ids&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;:ticket_id_n&lt;/code&gt; and &lt;code&gt;:ticket_value_n&lt;/code&gt; placeholders will be replaced by the corresponding values in the replacements object provided to Sequelize. This dynamic construction not only prevents SQL injection but also improves performance significantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance Gains
&lt;/h3&gt;

&lt;p&gt;Although the code still loops through the input array to build the query, the big improvement is that it only makes one database call for all updates. This drastically reduces the number of database interactions, making the application much faster, especially when handling a large number of tickets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In my experience building backend applications and APIs, it’s common to encounter scenarios where we need to update multiple records in the database. While looping through each item and making individual calls works, it's not scalable. By using &lt;code&gt;CASE&lt;/code&gt; statements and bulk queries, we can efficiently update multiple records in a single call, resulting in significant performance gains.&lt;/p&gt;

</description>
      <category>sql</category>
      <category>typescript</category>
      <category>backenddevelopment</category>
      <category>performance</category>
    </item>
    <item>
      <title>Turbocharge Your App: Slash DB Calls with Raw SQL Magic!</title>
      <dc:creator>Chidiebere Ogujeiofor</dc:creator>
      <pubDate>Tue, 24 Sep 2024 18:34:59 +0000</pubDate>
      <link>https://dev.to/chidioguejiofor/reducing-number-of-db-calls-2kjp</link>
      <guid>https://dev.to/chidioguejiofor/reducing-number-of-db-calls-2kjp</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In my experience building backend applications, one of the key factors in improving performance is reducing the number of I/O operations—such as database calls and external API requests—your app makes. Every I/O operation adds latency and can bottleneck your application's overall performance.&lt;/p&gt;

&lt;p&gt;Of all I/O operations, database queries are the most common, and if not optimized, can severely slow down your app. In this series of articles, I will explore common scenarios where an application might make multiple database calls unnecessarily and demonstrate techniques to optimize those operations.&lt;/p&gt;

&lt;p&gt;We will use a PostgreSQL database for the examples, but the techniques discussed can be applied to any SQL-based database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Articles in the series
&lt;/h3&gt;

&lt;p&gt;In this series, I dive into two key scenarios where we often end up making more database queries than necessary—and how to optimize them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/chidioguejiofor/scenario-1-making-updates-to-multiple-fields-56hl"&gt;Scenario 1: Multi-Row Updates with Unique Values&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When updating multiple rows with different values, we usually fire off individual update queries for each row, which can slow things down. In this article, I break down the issue and show how to tackle it more efficiently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/chidioguejiofor/scenario-2-back-filling-data-of-a-new-column-3o05"&gt;Scenario 2: Backfilling Data for New Columns&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adding a new column to a table with existing data? Backfilling that column can be a challenge. In this article, I demonstrate a raw SQL approach that simplifies the process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample Data
&lt;/h3&gt;

&lt;p&gt;For our examples, we will use a simplified schema of a ticketing application. The app allows event owners to create and manage events, while users can purchase tickets through an API.&lt;/p&gt;

&lt;p&gt;Here are the sample tables we'll work with:&lt;/p&gt;

&lt;h4&gt;
  
  
  Users Table
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Fields&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Constraints&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;first_name&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;last_name&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;VARCHAR(30)&lt;/td&gt;
&lt;td&gt;PK&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  events Table
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Fields&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Constraints&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;owner_id&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;FK -&amp;gt; Users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;VARCHAR(30)&lt;/td&gt;
&lt;td&gt;PK&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  tickets Table
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Fields&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Constraints&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;event_id&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;FK -&amp;gt; events&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;VARCHAR(30)&lt;/td&gt;
&lt;td&gt;PK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;amount&lt;/td&gt;
&lt;td&gt;INT&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;quantity&lt;/td&gt;
&lt;td&gt;INT&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;quantity_sold&lt;/td&gt;
&lt;td&gt;INT&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;quantity&lt;/code&gt;: represents the number of that tickets that is available at the beginning. This would be like the number of seats in a concert&lt;br&gt;
&lt;code&gt;quantity_sold&lt;/code&gt;: is the number of tickets that has been sold. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  See you in the next article
&lt;/h3&gt;

&lt;p&gt;Let's explore the first type of problem in the next article.&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%2F2689cybqf8y80as6kltd.gif" 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%2F2689cybqf8y80as6kltd.gif" alt="Alt text of image" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>typescript</category>
      <category>performance</category>
      <category>sequelize</category>
    </item>
    <item>
      <title>Crunch the frontend</title>
      <dc:creator>Chidiebere Ogujeiofor</dc:creator>
      <pubDate>Wed, 16 Aug 2023 08:58:29 +0000</pubDate>
      <link>https://dev.to/chidioguejiofor/crunch-the-frontend-1d3e</link>
      <guid>https://dev.to/chidioguejiofor/crunch-the-frontend-1d3e</guid>
      <description>&lt;p&gt;In the previous article, I talked about the different things that I tried and how I came up with an initially deployment strategy of hosting a PWA on Google PlayStore using the TWA technology&lt;/p&gt;

&lt;p&gt;Let's talk about the work that was done on the project so far.&lt;/p&gt;

&lt;p&gt;Note that the date of this writing is Aug 16th.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 7(Aug 9th) to Day 9(Aug 11th)
&lt;/h2&gt;

&lt;p&gt;In this period, I started by deleting some of the junk react native code that I added to the project when trying experimenting merging both react native and next js in the same project. &lt;/p&gt;

&lt;p&gt;After that, I went on the implement components for the connections, notification, settings and events page. Previously I had done the empty states of these pages but now I implemented the page with content. &lt;/p&gt;

&lt;p&gt;Note that since we do not have a backend api yet all of these are just staitic dummy pages. &lt;/p&gt;

&lt;p&gt;Also whent on to create modals that would allow users to edit their profile and invite people to the application. &lt;/p&gt;

&lt;h2&gt;
  
  
  Day 10(Aug 12th) to Day 11(Aug 13th)
&lt;/h2&gt;

&lt;p&gt;These 2 days were weekends and since I had made good progress in the project, I didn't touch it at all and used that as an opportunity to catch up with friends. &lt;/p&gt;

&lt;p&gt;It is very important to have maintain this balance. If not one is at the risk of burn out.&lt;/p&gt;

&lt;p&gt;It was also an opportunity to relax my mind and take a break everything&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 12(Aug 14th) to Day 16(Aug 17th)
&lt;/h2&gt;

&lt;p&gt;I didn't do much on these days because I fell ill on Aug 15th and I am currently on medication while writing this.&lt;/p&gt;

&lt;p&gt;However, the current plan is to test out that deployment assumption and convert the app to a PWA before moving forward. &lt;/p&gt;

&lt;p&gt;I would like to test that idea as early as possible so as not to be surprised when I am actually ready to deploy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;If I can do create the PWA quickly then I would start working on the backend. &lt;/p&gt;

&lt;p&gt;My strategy there is to comsume the API as I create them. &lt;/p&gt;

&lt;p&gt;This is the list of things that the API should be able to do:&lt;/p&gt;

&lt;p&gt;1.Authentication&lt;br&gt;
  a. Login with Google&lt;br&gt;
  b. Login with Password and Email&lt;br&gt;
  c. Signup with email and password&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create,Update and Delete Events&lt;/li&gt;
&lt;li&gt;Send connection request&lt;/li&gt;
&lt;li&gt;Accept connection request&lt;/li&gt;
&lt;li&gt;Remove connection&lt;/li&gt;
&lt;li&gt;Send emails to users:
a. Setup email sending with AWS SES
b. Create templates for Authentication
c. Create templates for upcoming events reminder
d. Create templates for &lt;/li&gt;
&lt;li&gt;Send emails when:
a. User registers
b. Beginning of the month with a list of upcoming events for that month&lt;/li&gt;
&lt;li&gt;User can edit profile&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Looks almost like I haven't even started&lt;/p&gt;

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

&lt;p&gt;Had a bit of set back with the illness but hopefully I'll be back very quickly and conver more grounds in this one&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Journey of a thousand miles</title>
      <dc:creator>Chidiebere Ogujeiofor</dc:creator>
      <pubDate>Wed, 09 Aug 2023 12:25:45 +0000</pubDate>
      <link>https://dev.to/chidioguejiofor/journey-of-a-thousand-miles-2mdi</link>
      <guid>https://dev.to/chidioguejiofor/journey-of-a-thousand-miles-2mdi</guid>
      <description>&lt;p&gt;I recently started working on a personal project whose aim is to help users remember their birthdays, anniversaries and any special dates that is important to them. &lt;/p&gt;

&lt;p&gt;The app includes features like creating events, sharing and connecting with others.&lt;/p&gt;

&lt;p&gt;My goal in this series is to document the decisions and thought process I have had throughout the journey so as to be able to share with others in the future. &lt;/p&gt;

&lt;p&gt;Think of this as an online journal dedicated to this project. &lt;/p&gt;

&lt;h2&gt;
  
  
  Project Technical Requirement
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The project is to be built as a mobile app(android and iOS) and web app (&lt;a href="https://never4get.app"&gt;https://never4get.app&lt;/a&gt;). We believe that the best usecase/experience is the native app.&lt;/li&gt;
&lt;li&gt;We would have a backend that would service both projects&lt;/li&gt;
&lt;li&gt;Login should preferably be with Google and Apple ID&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Initial Plan
&lt;/h2&gt;

&lt;p&gt;My very first goal is to build the application as quickly as possible and get it to the hands of users so as to be able to  get quick feedback and iterate the solution. &lt;/p&gt;

&lt;p&gt;Basically following the lean startup ideas.&lt;/p&gt;

&lt;p&gt;Since I am an expert in building web apps(both backend and frontend) but haven't written a single line of mobile app code before this project, I decided that it would be great if I could build a website and then use tools that can convert a web app to a native app with out writing any code. &lt;/p&gt;

&lt;p&gt;This was my initial plan and my first goal was to test this possibility as quickly as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 1 to 2
&lt;/h2&gt;

&lt;p&gt;The first day of development was August 3rd 2023. And in 3 days I was able to build the welcome page, sign in page, login with google and  onboarding screen after sign in. &lt;/p&gt;

&lt;p&gt;The part that took me a tiny time to figure out was the animation in the welcome page and how Next 13 &lt;code&gt;app&lt;/code&gt; directory works(this is the first project where I was using it) including the difference between server-side and client side components.&lt;/p&gt;

&lt;p&gt;This rapid progress made me realise that I could finish the frontend very quickly if I continued. I however thought it was now time to test out the idea of converting the website to a mobile app&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 3(Aug 5th): Experimenting
&lt;/h2&gt;

&lt;p&gt;On this day I started researching the different options of converting a website to a native app easily. &lt;/p&gt;

&lt;p&gt;For a long time I had thought that Enzyme was the tool for this job but I quickly realised that it is used to convert websites to desktop apps and not native mobile app(android/iOS). &lt;/p&gt;

&lt;p&gt;On further investigation I found Capacitor a tool that promises to do this well. Looked like something that would come out well. &lt;/p&gt;

&lt;p&gt;After running a few experiments and actually build the website and run it using capacitor and immediately found that the native experience was worse than it was on the web. &lt;/p&gt;

&lt;p&gt;These findings brought me to the final conclusion that the best way to move forward was to use a specialised tool and since I had a lot of experience working with React, I settled for React Native.&lt;/p&gt;

&lt;p&gt;The first experiment I ran was to see if I could keep the react-native and react code in the same codebase but I couldn't get this to work (as it kept throwing an "invalid Router" error). Thus, I decided that to separate these into 2 different projects. &lt;/p&gt;

&lt;h2&gt;
  
  
  Day 4(Aug 6th) - Day 7(Aug 9th): React Native
&lt;/h2&gt;

&lt;p&gt;I was able to leverage both the React Native documentation to setup the project using expo Go and configure tailwind(note that tailwind is also used in the web). &lt;/p&gt;

&lt;p&gt;I really dislike the way React Native styles component by default but since I was able to add tailwind, I found that I could re-use a lot of the styles from the web. &lt;/p&gt;

&lt;p&gt;Thus, I was able to copy and paste components from the web project and change their styling and "elements" to use native elements. &lt;/p&gt;

&lt;p&gt;However, there was still a lot of work. I couldn't get the login with Google to work, rendering SVGs required extra effort, a simple &lt;code&gt;transition:&lt;/code&gt; was implemented using a whole new component(Animation.View) etc. It required a lot of googling to understand what was going on. &lt;/p&gt;

&lt;p&gt;Even though I couldn't get the login with Google to work, I was able to roughly get to the place I was on web. I did the welcome, onboarding, signin and events screen in this time. Copying, pasting(and a lot of), refactoring code from the web to get it to work in the early morning(aka 12 am ish) of August 9th&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 7(Aug 9th): Way forward
&lt;/h2&gt;

&lt;p&gt;As at the time of this writing we are currently at 1pm Aug 9th. I have thought about the best strategy to maintain speed and momentum in this project and I am aware that using React Native is going to slow things down a bit. &lt;/p&gt;

&lt;p&gt;There are still unknowns like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login with Apple&lt;/li&gt;
&lt;li&gt;Notification API on native apps&lt;/li&gt;
&lt;li&gt;Payments and how it would work &lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thus, I have decided to build the web app end to end this month, launch it(aka show a few people how it works),  get  feedback as quick as possible then gradually work on the native android and iOS from next month.&lt;/p&gt;

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

&lt;p&gt;So far so good. Good progress has been made and a final plan hatched. &lt;/p&gt;

&lt;p&gt;It is also interesting to see how much can happen in 8 days.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Automatically notify your team when you deploy new changes in a Python project</title>
      <dc:creator>Chidiebere Ogujeiofor</dc:creator>
      <pubDate>Sun, 12 Dec 2021 15:17:52 +0000</pubDate>
      <link>https://dev.to/stears/automatically-notify-your-team-when-you-deploy-new-changes-5bf1</link>
      <guid>https://dev.to/stears/automatically-notify-your-team-when-you-deploy-new-changes-5bf1</guid>
      <description>&lt;p&gt;Photo from &lt;code&gt;ThisisEngineering&lt;/code&gt;&lt;a href="https://www.pexels.com/photo/female-software-engineer-coding-on-computer-3861972/" rel="noopener noreferrer"&gt;Pexels&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;One of the things that I love about the &lt;a href="https://en.wikipedia.org/wiki/Scrum_software_development" rel="noopener noreferrer"&gt;Agile methodology&lt;/a&gt; is how it gives you the ability to make frequent tiny improvements to your project. An essential advantage of “being” Agile is deploying small changes frequently that add value to our customers or improve some internal processes.&lt;/p&gt;

&lt;p&gt;In scrum, we would usually have a demo after every sprint in which we show new features/changes to other stakeholders(design, data, non-technical teammates etc.). However, in these demos, we rarely go into the minute details of the new changes (e.g. a column being renamed in a database table or the meaning of a column changing). These omissions could lead to problems with teams that depend on your work. &lt;/p&gt;

&lt;p&gt;Imagine that you have a web team(that adds and maintains features on your web app) and a data team(that analyses the data generated by your web app to perform different tasks). Let’s say the web team deploys a feature that replaces a boolean &lt;strong&gt;is_customer&lt;/strong&gt; field with a role field(that has enum CUSTOMER, SHOP_OWNER, ADMIN). The problem here is that during demos at the end of the sprint, the web team would often communicate the “new features” that were added and may forget to talk about the column change.  &lt;/p&gt;

&lt;p&gt;After deploying such changes, the existing queries of the data team would suddenly stop working or give incorrect results.&lt;/p&gt;

&lt;p&gt;Also, imagine that a non-technical teammate(e.g. a marketer) was to ask you when the web team deployed the “google login” feature to the website; where would you find that information?&lt;/p&gt;

&lt;p&gt;We experienced these problems in my team at &lt;a href="https://www.stearsng.com/" rel="noopener noreferrer"&gt;Stears&lt;/a&gt;, and I think our solutions to all of them are related. In this article, I would like to share a high-level view of how we solved this.&lt;/p&gt;

&lt;p&gt;Below is a summary of the problems we found:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Demos usually omits crucial minute changes to the other team members, and we need a way to notify them when we deploy automatically.&lt;/li&gt;
&lt;li&gt;There was no place to see the history of changes that we made in the past&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is how the rest of the article structured:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How we solved this&lt;/li&gt;
&lt;li&gt;Link between changelog and commit convention&lt;/li&gt;
&lt;li&gt;Choosing a commit convention&lt;/li&gt;
&lt;li&gt;Enforcing a commit convention&lt;/li&gt;
&lt;li&gt;Generating a changelog&lt;/li&gt;
&lt;li&gt;Sending the message to slack&lt;/li&gt;
&lt;li&gt;Sending different messages from the pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How we solved this &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We deploy new changes to production in our system by creating a release &lt;a href="https://docs.gitlab.com/ee/topics/git/tags.html" rel="noopener noreferrer"&gt;tag&lt;/a&gt;. Once a release is created, a manual job in our pipeline, which when run deploys our app to production.&lt;/p&gt;

&lt;p&gt;Since our deployment strategy involved creating tags and changelogs contain information about the changes that have been deployed in each release, we decided to solve the problems stated above by maintaining a changelog in our project.&lt;br&gt;
Adding a changelog led us to choose a commit convention, enforce it, and add commands that extract the most recent changes from our changelog and send it to slack whenever we deploy.&lt;/p&gt;
&lt;h3&gt;
  
  
  Link between changelog and commit convention &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Maintaining a CHANGELOG lets us know the releases(and the changes within each release) that have been made historically and allows us to extract the most recent updates easily. &lt;/p&gt;

&lt;p&gt;For us, we also wanted our changelog to have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a link to the ticket so we can see more details about each change&lt;/li&gt;
&lt;li&gt;a link  that shows us the file changes that were made while implementing that feature&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below is an example of how our changelog looks:&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%2Fn786vchfhsj355qnjwsl.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%2Fn786vchfhsj355qnjwsl.png" alt="Changelog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have used dummy messages here. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice how the changelog shows the date the web team deployed each release and how it groups the changes based on their type(bug fixes, features, automation, etc.)&lt;/p&gt;

&lt;p&gt;Manually updating this information to your changelog is going to be painful. &lt;/p&gt;

&lt;p&gt;Since we usually add a description of changes made in our commit messages, it makes sense to use these messages to automate the way we generate our changelog. To do this, however, we needed to have a consistent commit message format(a commit convention) so as to easily extract the data we want to be in our changelog. &lt;/p&gt;

&lt;p&gt;Next, let’s talk about how we chose our commit convention.&lt;/p&gt;
&lt;h4&gt;
  
  
  Choosing a commit convention &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;When choosing a commit convention, you have to decide what data you want your commit to have. There is a standard called &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;conventional commit&lt;/a&gt; which has the following structure&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;type&amp;gt;[optional scope]: &amp;lt;description&amp;gt;
&amp;lt;new-line&amp;gt;
[optional body]
&amp;lt;new-line&amp;gt;
[optional footer(s)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The “type” section is used to state whether the commit is a feature(feat), refactor, ci change, etc.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;scope&lt;/code&gt; is one or two words that give a general context of the task. This is usually the name of the epic the commit is part of. E.g. authentication, notification, subscription etc&lt;/li&gt;
&lt;li&gt;The “description” is one sentence or phrase that describes the task&lt;/li&gt;
&lt;li&gt;The “body” is where you add more details of the task&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Footers&lt;/code&gt; are where you specify extra details like whether the task is a breaking change, ticket number etc. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For us in my team, however, we decided to make slight changes to this by &lt;br&gt;
replacing the ‘footer’ part with a required issue_number and &lt;br&gt;
ensuring that the optional body is in bullet points(when provided). &lt;/p&gt;

&lt;p&gt;We did this because we wanted to ensure that the issue number was always in the message we sent to our teammates on deployment. &lt;/p&gt;

&lt;p&gt;Below is the structure of the commit convention we chose&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;type&amp;gt;[optional scope]: &amp;lt;description&amp;gt;
&amp;lt;required blank-line&amp;gt;
[optional bullet point body]
&amp;lt;required blank-line&amp;gt;
closes docs#&amp;lt;required issue_number&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F6825saroyxfc0sp1c8s5.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%2F6825saroyxfc0sp1c8s5.png" alt="Commit structure and example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Examples of valid commits are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1&lt;/strong&gt;: &lt;em&gt;scope and body is present&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(auth): Adds signup page to the app

- adds signup.html file to the app 

closes docs#101
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt;: &lt;em&gt;body and scope not provided&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chore: Refactors auth folder 

closes docs#121
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 3:&lt;/strong&gt;: &lt;em&gt;scope provided but body omitted&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ci(deploy): Improve deploy changes

closes docs#121
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we get to the practical section of this series, you will see that you could use any format you want as long as it is consistent and has all the information you want. To ensure consistency, you would have to enforce it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Enforcing commit convention &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;It is one thing for everybody to agree on a commit convention, but it is very easy for mistakes and typos to be made when writing commits. Thus, it would be best to enforce the convention you choose on your local machine and on a CI pipeline to ensure that everyone obeys/follows it. &lt;/p&gt;

&lt;p&gt;We achieved this by adding a command to our pre-commit hook that validates that our commit messages followed our convention and added the same check to our CI pipeline.&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%2F1swvpvoyqhee82j0yav4.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%2F1swvpvoyqhee82j0yav4.png" alt="Stears Commit convention"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To enforce the agreed commit convention, we used a tool called &lt;a href="https://commitizen-tools.github.io/commitizen/" rel="noopener noreferrer"&gt;commitizen&lt;/a&gt; which reads a regex specified in a &lt;code&gt;cz.toml&lt;/code&gt; configuration file to test each commit message that is created. You will see how we did this when we get to the implementation detail section.&lt;/p&gt;

&lt;p&gt;Once we have enforced our commit conventions, the next thing we do is to generate a changelog. &lt;/p&gt;

&lt;h4&gt;
  
  
  Generating the changelog &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;The &lt;a href="https://commitizen-tools.github.io/commitizen/" rel="noopener noreferrer"&gt;commitizen&lt;/a&gt; package also allows you to generate a changelog from your commit messages.&lt;/p&gt;

&lt;p&gt;To achieve this, we had to determine how we wanted each bullet point that highlights a change to look, create a grouped regex that extracts the parts of our commit message and use a class-based configuration from the commitizen package.&lt;/p&gt;

&lt;p&gt;I will show you how I did this in a subsequent article.&lt;/p&gt;

&lt;p&gt;So now we have the valid commits, and we have a changelog its time to talk about slack.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sending the message to slack &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;After generating the changelog, the final step is to add code that automatically extracts the most recent release from the changelog and add it to the slack message. &lt;/p&gt;

&lt;p&gt;We achieved this by creating a &lt;a href="https://api.slack.com/bot-users" rel="noopener noreferrer"&gt;slack bot&lt;/a&gt; in our slack workspace and programmatically sending messages to a channel via a slack client. &lt;/p&gt;

&lt;p&gt;While doing this, however, we quickly realised that slack does not recognise markdown but has its own rules for achieving  &lt;a href="https://api.slack.com/messaging/composing/layouts" rel="noopener noreferrer"&gt;rich text formatting&lt;/a&gt; via its API. Let’s call this slack technique of formatting messages “slackdown” (a fancy name invented by my manager)&lt;/p&gt;

&lt;p&gt;As a result, we created a parser that converts markdown to “slackdown” alongside building a slack client. Once this parser has been completed, sending the slack message becomes easy.&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%2Fl1e0zsxzm7uvm9mzpy76.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%2Fl1e0zsxzm7uvm9mzpy76.png" alt="Difference between  markdown and slack rich text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Sending different messages from the pipeline &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Once the slack bot has been created and is working, the next step is to develop different commands that would run on different scenarios(or events) in the pipeline. In our case, we needed a CLI command that would send a message on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;QA-deploy-success&lt;/li&gt;
&lt;li&gt;QA-deploy-failure&lt;/li&gt;
&lt;li&gt;prod-deploy-success&lt;/li&gt;
&lt;li&gt;prod-deploy-failure&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Hurray! If you got here, then you are fantastic! This article discussed a lot, and I explained the steps we took to maintain a changelog and notify our teammates when we deploy new features.&lt;/p&gt;

&lt;p&gt;In asubsequent article, I will take you through each step with code examples. &lt;/p&gt;

&lt;p&gt;You can follow &lt;a href="https://dev.to/stears"&gt;StearsBusiness&lt;/a&gt; to get notified once it is created.&lt;/p&gt;

</description>
      <category>git</category>
      <category>changelog</category>
      <category>devops</category>
    </item>
    <item>
      <title>Methods of Data Storage in Data Science You Should Know</title>
      <dc:creator>Chidiebere Ogujeiofor</dc:creator>
      <pubDate>Fri, 18 Jun 2021 22:26:02 +0000</pubDate>
      <link>https://dev.to/chidioguejiofor/methods-of-data-storage-in-data-science-you-should-know-7j1</link>
      <guid>https://dev.to/chidioguejiofor/methods-of-data-storage-in-data-science-you-should-know-7j1</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@artwall_hd?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Art Wall - Kittenprint&lt;/a&gt;  on &lt;a href="https://images.unsplash.com/photo-1591913139332-f8172ef511da?ixlib=rb-1.2.1&amp;amp;ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;w=3300&amp;amp;q=80"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;We live in extraordinary times where technology is part of everything. One of the things that have made technology so powerful and valuable is data. A vast amount of data is generated every day on the internet. Consider the data generated on Instagram alone:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;500 million Instagram stories are uploaded everyday&lt;/li&gt;
&lt;li&gt;3.5 billion likes are recorded daily&lt;/li&gt;
&lt;li&gt;As of 2016, 95 million posts are made every day, and Instagram usage doubled between 2016 and 2018.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This massive amount of data (called big data because of the size) cannot be stored using traditional techniques or on one machine.  Storing and retrieving &lt;strong&gt;big data&lt;/strong&gt; requires multiple interconnected machines. This article focuses on the different techniques of storing big data and their pros, cons, and use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of Data
&lt;/h2&gt;

&lt;p&gt;Before diving into the different types of data storage, we must first look at the types of data. &lt;/p&gt;

&lt;h3&gt;
  
  
  Structured Data
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developers.google.com/search/docs/guides/intro-structured-data"&gt;Structured data&lt;/a&gt; is anything that you can easily store in an excel spreadsheet, such as user first name, last name, bank details, etc. Such data usually has a defined length and format. On the internet, structured data is generated by both humans and machines. Some sources of this data are listed below:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Human&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Filling your details or information on a form&lt;/li&gt;
&lt;li&gt;Behaviour while watching videos online. For example, the site tracks the timestamp/episode you left the video at last.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Machine&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sensor data from your IoT devices or smartphones like your GPS location, battery life, and so on&lt;/li&gt;
&lt;li&gt;Application logs, which help engineers figure out what errors exist in their platform or how efficient their system works.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Structured data accounts for about 20% of all the data on the internet and is usually easy to analyze to derive meaningful insights. &lt;/p&gt;

&lt;h3&gt;
  
  
  Unstructured Data
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Unstructured_data"&gt;Unstructured data&lt;/a&gt; does not have any predefined format or model. You will usually not find a lot of similarities between 2 objects of this type of data. Classic examples of unstructured data are videos, images, audio, etc. If you were given two audio files, the difference in the author’s voice alone leads to a considerable difference between the two files. Like structured data, unstructured data also has its human and machine sources. Some of these include:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Human&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Posting that morning sunshine image on Instagram&lt;/li&gt;
&lt;li&gt;Updating your WhatsApp status with a comic video&lt;/li&gt;
&lt;li&gt;Live streaming on social media platforms&lt;/li&gt;
&lt;li&gt;The last PDF you exported&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Machine&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Images of the earth taken from a satellite&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Analyzing unstructured data is more complex and usually involves creating machine learning models. This data comprises about 80% of the data on the internet and has become easier to store and maintain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t3eTmrjy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bpljh599f1c8udy7ne7r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t3eTmrjy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bpljh599f1c8udy7ne7r.png" alt="Structured VS Unstructured Data"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    &lt;a href="https://lawtomated.com/structured-data-vs-unstructured-data-what-are-they-and-why-care/"&gt;Image Source&lt;/a&gt;&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Semi-structured Data&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;I like to think of this type of data as a kind of hybrid of both the above-mentioned types. It usually contains a structured part and an unstructured part. &lt;/p&gt;

&lt;p&gt;Some examples of semi-structured data are emails and word documents. Notice these contain text (structured data) and media files (unstructured data). Think now of the data stored in NoSQL DBs in which one item has a certain number of fields, but the next does not—that is a semi-structured dataset. Notice that an email has the to, from, cc, and bcc fields, which are structured data, but it may also contain images.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Store Data
&lt;/h2&gt;

&lt;p&gt;Now that we have familiarised ourselves with the different types of data, we can look at the various methods of storing this data. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4yeU66VD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.caringo.com/wp-content/uploads/2017/01/File-Object-Storage.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4yeU66VD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.caringo.com/wp-content/uploads/2017/01/File-Object-Storage.svg" alt="Alt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.caringo.com/blog/back-basics-object-storage"&gt;Image Source&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  File Storage
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.ibm.com/cloud/learn/file-storage"&gt;In this type of storage&lt;/a&gt;, data is stored in data form on a disk. Anyone who wants to access it has to know the file path of the information on the disk. Some other characteristics of file storage include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Files can simultaneously be read and written.&lt;/li&gt;
&lt;li&gt;Only users on the same network can access them.&lt;/li&gt;
&lt;li&gt;It is not easy to replicate your data—you might lose data in case of machine failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Block Storage
&lt;/h3&gt;

&lt;p&gt;In block storage, data is stored as a contiguous chunk (called a block). It allows us to spread our network easily across different networks, and you don’t need to know where it is stored on the disk to access it. Relational databases are examples of RDMS, making it the best type of storage for structured data. &lt;/p&gt;

&lt;p&gt;Other characteristics include:&lt;br&gt;
They are highly scalable: You can increase the size of your block storage by adding more nodes to your network, thus making it easy to scale.&lt;br&gt;
Easy to replicate: Most block storage services are easy to backup/replicate. Thus, in case of machine failure, your data is still intact.&lt;br&gt;
Reads and writes are fast, and you do not need to know where the data is on disk.&lt;br&gt;
Block storage is generally expensive as the data increases. This makes it expensive for data that is large, for instance. &lt;/p&gt;

&lt;h3&gt;
  
  
  Object Storage
&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://lakefs.io/object-storage"&gt;Object storage&lt;/a&gt; is the most suitable way of storing unstructured data. The data is usually stored as an “object”.&lt;/p&gt;

&lt;p&gt;An object is made up of 3 main parts: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The data: This is the image, picture, etc., that we want to store.&lt;/li&gt;
&lt;li&gt;Metadata: This can be a description of what this data stands for. Most object storage services allow us to search the content of this metadata.&lt;/li&gt;
&lt;li&gt;Unique Identifier: This can be used to retrieve the object easily at any point.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anytime an object is created, most services replicate it three times. This makes it easy to retrieve the object and search for the data. Thus, object storage is ideal for storing unstructured data as it can easily be accessed using an ID.&lt;/p&gt;

&lt;p&gt;Advantages of object storage include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Way cheaper than other types of storage&lt;/li&gt;
&lt;li&gt;Data replication comes in by default&lt;/li&gt;
&lt;li&gt;Rich metadata feature&lt;/li&gt;
&lt;li&gt;The storage is not coupled to a machine and thus is easy to scale&lt;/li&gt;
&lt;li&gt;Grouping of data can be done using a metadata value&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;In this article, we looked at the different types of data in big data and explored the main techniques of storing big data. I hope you learn something new from this article. &lt;/p&gt;

</description>
      <category>datascience</category>
      <category>database</category>
      <category>bigdata</category>
    </item>
    <item>
      <title>Relative calculations 1: LAG and LEAD</title>
      <dc:creator>Chidiebere Ogujeiofor</dc:creator>
      <pubDate>Sun, 20 Sep 2020 19:28:25 +0000</pubDate>
      <link>https://dev.to/chidioguejiofor/relative-calculations-1-lag-and-lead-47cj</link>
      <guid>https://dev.to/chidioguejiofor/relative-calculations-1-lag-and-lead-47cj</guid>
      <description>&lt;p&gt;In this post, we are going to continue our discussion by looking at calculations that involve getting the value from the previous/next row. We would see how using &lt;code&gt;ORDER BY&lt;/code&gt; clause in an SQL window function can make these calculations pretty easy and possible.&lt;/p&gt;

&lt;p&gt;Let's dive right in. &lt;/p&gt;

&lt;h3&gt;
  
  
  Our Big Question
&lt;/h3&gt;

&lt;p&gt;One particularly important insight is the increase is the way the number of cases has been increasing. Suppose we had the following question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What is the increase in cases recorded in the UK for each day in the month of June?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Assuming we had access to only the total number of confirmed cases one way we could answer this to generate a table where each row gives us the difference between the case recorded today and the case recorded previous day. Soemthing like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;date&lt;/th&gt;
&lt;th&gt;total_confirmed_cases&lt;/th&gt;
&lt;th&gt;daily_case_recorded&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-01&lt;/td&gt;
&lt;td&gt;v1
&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-02&lt;/td&gt;
&lt;td&gt;v2
&lt;/td&gt;
&lt;td&gt;v2 - v1
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-03&lt;/td&gt;
&lt;td&gt;v3
&lt;/td&gt;
&lt;td&gt;v3 - v2
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-04&lt;/td&gt;
&lt;td&gt;v4
&lt;/td&gt;
&lt;td&gt;v4 - v3
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.&lt;/td&gt;
&lt;td&gt;.&lt;/td&gt;
&lt;td&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.&lt;/td&gt;
&lt;td&gt;.&lt;/td&gt;
&lt;td&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.&lt;/td&gt;
&lt;td&gt;.&lt;/td&gt;
&lt;td&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;n&lt;/td&gt;
&lt;td&gt;vn
&lt;/td&gt;
&lt;td&gt;vn - vn-1
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notice how the value in each row in the &lt;em&gt;total_confirmed_cases&lt;/em&gt; column uses the value from the previous column to calculate its value. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that we assumed that we had access to only the &lt;em&gt;total_confirmed_cases&lt;/em&gt;. Google COVID Dataset already gives us the daily_confirmed_cases which is the same as what we want to calculate.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In order to solve this, we would use the LAG aggregate function and ORDER BY in our window function.&lt;/p&gt;




&lt;h3&gt;
  
  
  The ORDER BY in a window function
&lt;/h3&gt;

&lt;p&gt;Using the ORDER BY as an argument in the window function specifies how you want the window function to sort the rows in the ResultSet while performing calculations. &lt;/p&gt;

&lt;p&gt;For example, in order to answer the question we have above, it is important that we sort the result by date so that when getting the value from the previous row, we would be getting the confirmed case from the previous day. &lt;/p&gt;

&lt;p&gt;Using the ORDER BY clause makes it possible for us to specify that. &lt;/p&gt;

&lt;p&gt;We can use the ORDER BY like so:&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;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;column_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;column_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...,&lt;/span&gt; &lt;span class="n"&gt;column_n&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;ASC&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  LAG aggregate function
&lt;/h3&gt;

&lt;p&gt;The LAG function is a special aggregate function the works only when used with window functions. It takes a column as an argument and returns the previous value of that column in the ResultSet. &lt;/p&gt;

&lt;p&gt;We use the LAG function with the ORDER BY clause like so:&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;LAG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;column_name&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;column_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;column_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...,&lt;/span&gt; &lt;span class="n"&gt;column_n&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="k"&gt;ASC&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The SQL QUERY
&lt;/h3&gt;

&lt;p&gt;Combining these together we can answer our Big question using 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="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;countries_and_territories&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;confirmed_cases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;confirmed_cases&lt;/span&gt; &lt;span class="o"&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;confirmed_cases&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="nb"&gt;date&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;daily_increase&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="nv"&gt;`bigquery-public-data.covid19_ecdc.covid_19_geographic_distribution_worldwide`&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
  &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nv"&gt;"2020-06-01"&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nv"&gt;"2020-06-30"&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;geo_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"UK"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This filters the resultset and generates the increase in a number of cases using:&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;confirmed_cases&lt;/span&gt; &lt;span class="o"&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;confirmed_cases&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="nb"&gt;date&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;daily_increase&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The window function orders by date while the  LAG(confirmed_cases) returns cases confirmed for the previous row. &lt;/p&gt;

&lt;p&gt;This generates the following table.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;date&lt;/th&gt;
&lt;th&gt;country&lt;/th&gt;
&lt;th&gt;confirmed_cases&lt;/th&gt;
&lt;th&gt;daily_increase&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-01&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;274762&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-02&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;276332&lt;/td&gt;
&lt;td&gt;1570&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-03&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;277985&lt;/td&gt;
&lt;td&gt;1653&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-04&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;279856&lt;/td&gt;
&lt;td&gt;1871&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-05&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;281661&lt;/td&gt;
&lt;td&gt;1805&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-06&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;283311&lt;/td&gt;
&lt;td&gt;1650&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-07&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;284868&lt;/td&gt;
&lt;td&gt;1557&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-08&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;286194&lt;/td&gt;
&lt;td&gt;1326&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-09&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;287399&lt;/td&gt;
&lt;td&gt;1205&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-10&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;289140&lt;/td&gt;
&lt;td&gt;1741&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-11&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;290143&lt;/td&gt;
&lt;td&gt;1003&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-12&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;291409&lt;/td&gt;
&lt;td&gt;1266&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-13&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;292950&lt;/td&gt;
&lt;td&gt;1541&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-14&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;294375&lt;/td&gt;
&lt;td&gt;1425&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-15&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;295889&lt;/td&gt;
&lt;td&gt;1514&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-16&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;296857&lt;/td&gt;
&lt;td&gt;968&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-17&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;298136&lt;/td&gt;
&lt;td&gt;1279&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-18&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;299251&lt;/td&gt;
&lt;td&gt;1115&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-19&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;300469&lt;/td&gt;
&lt;td&gt;1218&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-20&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;301815&lt;/td&gt;
&lt;td&gt;1346&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-21&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;303110&lt;/td&gt;
&lt;td&gt;1295&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-22&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;304331&lt;/td&gt;
&lt;td&gt;1221&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-23&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;305289&lt;/td&gt;
&lt;td&gt;958&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-24&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;306210&lt;/td&gt;
&lt;td&gt;921&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-25&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;306862&lt;/td&gt;
&lt;td&gt;652&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-26&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;307980&lt;/td&gt;
&lt;td&gt;1118&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-27&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;309360&lt;/td&gt;
&lt;td&gt;1380&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-28&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;310250&lt;/td&gt;
&lt;td&gt;890&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-29&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;311151&lt;/td&gt;
&lt;td&gt;901&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-30&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;311965&lt;/td&gt;
&lt;td&gt;814&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One thing that you may have noticed is that the first value in the table is &lt;strong&gt;NULL&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Remember what we said in previous articles that window functions use the ResultSet generated after filtering in the WHERE clause, well, this is one of the consequences. &lt;/p&gt;

&lt;p&gt;At the first instance, the LAG function returns the value of the specified column in the previous row but the first row does not have a previous row. Therefore, we get NULL( which means non-existent). &lt;/p&gt;

&lt;p&gt;But we know that the confirmed case for the first day of July exists, so how do we get that?&lt;/p&gt;

&lt;p&gt;One quick way is to modify the filter in the WHERE clause so that it returns data for a day before July 1st like so:&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;WHERE&lt;/span&gt;
  &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nv"&gt;"2020-05-31"&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nv"&gt;"2020-06-30"&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;geo_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"UK"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we omit the first row in our resultset by adding &lt;code&gt;OFFSET 1&lt;/code&gt;. The new query would now become&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="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;countries_and_territories&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;confirmed_cases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;confirmed_cases&lt;/span&gt; &lt;span class="o"&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;confirmed_cases&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="nb"&gt;date&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;daily_increase&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="nv"&gt;`bigquery-public-data.covid19_ecdc.covid_19_geographic_distribution_worldwide`&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
  &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nv"&gt;"2020-05-31"&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nv"&gt;"2020-06-30"&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;geo_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"UK"&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt;
  &lt;span class="mi"&gt;31&lt;/span&gt; &lt;span class="k"&gt;OFFSET&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would return the correct data for the  first row&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;date&lt;/th&gt;
&lt;th&gt;country&lt;/th&gt;
&lt;th&gt;confirmed_cases&lt;/th&gt;
&lt;th&gt;daily_increase&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-01&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;274762&lt;/td&gt;
&lt;td&gt;1936&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-02&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;276332&lt;/td&gt;
&lt;td&gt;1570&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-03&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;277985&lt;/td&gt;
&lt;td&gt;1653&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-04&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;279856&lt;/td&gt;
&lt;td&gt;1871&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-05&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;281661&lt;/td&gt;
&lt;td&gt;1805&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-06&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;283311&lt;/td&gt;
&lt;td&gt;1650&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-07&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;284868&lt;/td&gt;
&lt;td&gt;1557&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-08&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;286194&lt;/td&gt;
&lt;td&gt;1326&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-09&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;287399&lt;/td&gt;
&lt;td&gt;1205&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-10&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;289140&lt;/td&gt;
&lt;td&gt;1741&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-11&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;290143&lt;/td&gt;
&lt;td&gt;1003&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-12&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;291409&lt;/td&gt;
&lt;td&gt;1266&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-13&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;292950&lt;/td&gt;
&lt;td&gt;1541&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-14&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;294375&lt;/td&gt;
&lt;td&gt;1425&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-15&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;295889&lt;/td&gt;
&lt;td&gt;1514&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-16&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;296857&lt;/td&gt;
&lt;td&gt;968&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-17&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;298136&lt;/td&gt;
&lt;td&gt;1279&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-18&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;299251&lt;/td&gt;
&lt;td&gt;1115&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-19&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;300469&lt;/td&gt;
&lt;td&gt;1218&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-20&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;301815&lt;/td&gt;
&lt;td&gt;1346&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-21&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;303110&lt;/td&gt;
&lt;td&gt;1295&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-22&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;304331&lt;/td&gt;
&lt;td&gt;1221&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-23&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;305289&lt;/td&gt;
&lt;td&gt;958&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-24&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;306210&lt;/td&gt;
&lt;td&gt;921&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-25&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;306862&lt;/td&gt;
&lt;td&gt;652&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-26&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;307980&lt;/td&gt;
&lt;td&gt;1118&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-27&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;309360&lt;/td&gt;
&lt;td&gt;1380&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-28&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;310250&lt;/td&gt;
&lt;td&gt;890&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-29&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;311151&lt;/td&gt;
&lt;td&gt;901&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-06-30&lt;/td&gt;
&lt;td&gt;United_Kingdom&lt;/td&gt;
&lt;td&gt;311965&lt;/td&gt;
&lt;td&gt;814&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now we can generate our chart:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bSMFUuot--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/678b0h1j7d7qvpzfpgt8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bSMFUuot--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/678b0h1j7d7qvpzfpgt8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can interact with the chart by following &lt;a href="https://live.amcharts.com/0OTFj"&gt;this link&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  More on LAG, intro to LEAD
&lt;/h3&gt;

&lt;p&gt;The LAG function takes an optional integer as value as its second argument this integer indicates how many rows back we want to get. This number is 1 by default, that's why we get the previous row( 1 row before the current row). &lt;/p&gt;

&lt;p&gt;Similar to the LAG function is the LEAD function which takes the value of the next row. It has the same constraints and syntax of the LAG function. &lt;/p&gt;

&lt;p&gt;So LEAD(col_name, 2) indicate we want to get a value 2 rows after the current row from &lt;em&gt;col_name&lt;/em&gt; while &lt;em&gt;LEAD(col_name)&lt;/em&gt; indicate we want the next row value. &lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this article, we've learnt how to perform a calculation that involves getting a single value from a row before or after our current row. &lt;/p&gt;

&lt;p&gt;That's great but what if we want to perform an aggregation based on more than one row before or after our current row? We would see how to do that using ROWS PRECEDING and ROWS FOLLOWING in the next article of our series. &lt;/p&gt;

&lt;p&gt;See you soon.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/l1J3CbFgn5o7DGRuE/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/l1J3CbFgn5o7DGRuE/giphy.gif" alt="Take the lead"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>sql</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Comparing aggregated data to unaggregated data in SQL</title>
      <dc:creator>Chidiebere Ogujeiofor</dc:creator>
      <pubDate>Sun, 13 Sep 2020 15:44:54 +0000</pubDate>
      <link>https://dev.to/chidioguejiofor/comparing-aggregated-data-to-unaggregated-data-in-sql-3071</link>
      <guid>https://dev.to/chidioguejiofor/comparing-aggregated-data-to-unaggregated-data-in-sql-3071</guid>
      <description>&lt;p&gt;Depending on the type of questions we want to answer there might be times when we need to compare aggregated data to unaggregated data in SQL.&lt;/p&gt;

&lt;p&gt;This is where the fact that the GROUP BY clause forces us to 'squeeze' all unaggregated columns into one row can be a headache. &lt;/p&gt;

&lt;p&gt;In this article, you would see how a window function can make this quite easy. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Big question
&lt;/h3&gt;

&lt;p&gt;Suppose we wanted to answer the following question using our COVID Dataset:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How does each case recorded in Nigeria from March 2020 to June 2020 compared with the maximum case recorded within the same time frame.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can answer this question by returning a table that has the recorded case for each day and the maximum case recorded in a day within the time frame. Something like this: &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;date&lt;/th&gt;
&lt;th&gt;country&lt;/th&gt;
&lt;th&gt;confirmed_today&lt;/th&gt;
&lt;th&gt;max_value_in_timeframe&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-01&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;value1
&lt;/td&gt;
&lt;td&gt;&lt;em&gt;max_value_in_result_set&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-02&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;value2
&lt;/td&gt;
&lt;td&gt;&lt;em&gt;max_value_in_result_set&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-03&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;value3
&lt;/td&gt;
&lt;td&gt;&lt;em&gt;max_value_in_result_set&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-04&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;value4
&lt;/td&gt;
&lt;td&gt;&lt;em&gt;max_value_in_result_set&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This would allow us to easily plot graphs that help us with the comparison. Let's see how we can solve this&lt;/p&gt;




&lt;h3&gt;
  
  
  The Inefficient solution
&lt;/h3&gt;

&lt;p&gt;We can generate this result using a &lt;a href="https://dev.to/chidioguejiofor/sql-subqueries-in-action-2igp"&gt;subquery&lt;/a&gt; in the SELECT clause. This subquery would calculate the maximum value and return that value for each row in our table. See the code below:&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="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;countries_and_territories&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;daily_confirmed_cases&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;confirmed_today&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;MAX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;daily_confirmed_cases&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt;
      &lt;span class="nv"&gt;`bigquery-public-data.covid19_ecdc.covid_19_geographic_distribution_worldwide`&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt;
      &lt;span class="n"&gt;geo_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'NG'&lt;/span&gt;
      &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2020-03-01'&lt;/span&gt;
      &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="s1"&gt;'2020-06-01'&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;highest_case_recorded_in_a_day&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="nv"&gt;`bigquery-public-data.covid19_ecdc.covid_19_geographic_distribution_worldwide`&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
  &lt;span class="n"&gt;geo_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'NG'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2020-03-01'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="s1"&gt;'2020-06-01'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns the following results:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;date&lt;/th&gt;
&lt;th&gt;country&lt;/th&gt;
&lt;th&gt;confirmed_today&lt;/th&gt;
&lt;th&gt;highest_case_recorded_in_a_day&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-01&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;533&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-02&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-10&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-15&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-16&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-17&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-18&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-19&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-20&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-21&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-22&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-23&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-24&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-25&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-26&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-27&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-28&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-29&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-30&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-03-31&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-01&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-02&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-03&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-04&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-05&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-06&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-07&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-08&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-09&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-10&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-11&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-12&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-13&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-14&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-15&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-16&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-17&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-18&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;51&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-19&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;49&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-20&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;85&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-21&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;38&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-22&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;117&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-23&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;91&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-24&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;108&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-25&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;114&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-26&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;87&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-27&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;91&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-28&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-29&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;195&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-04-30&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;196&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-01&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;204&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-02&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;238&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-03&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;218&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-04&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;170&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-05&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;244&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-06&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;148&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-07&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;195&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-08&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;381&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-09&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;386&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-10&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;239&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-11&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;248&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-12&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;242&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-13&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;146&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-14&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;184&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-15&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;191&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-16&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;283&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-17&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;176&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-18&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;338&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-19&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;216&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-20&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;226&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-21&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;276&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-22&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;339&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-23&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;245&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-24&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;265&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-25&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;313&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-26&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;229&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-27&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;276&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-28&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;389&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-29&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;182&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-30&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;387&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020-05-31&lt;/td&gt;
&lt;td&gt;Nigeria&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;td&gt;553&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As you can see it returns exactly the shape of the data that we want in our table. Now we can go ahead and generate a chart, like the one shown below, which are easier to comprehend:&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%2Fi%2F3077n4rsle9t0p9v4f0d.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%2Fi%2F3077n4rsle9t0p9v4f0d.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can interact with the chart &lt;a href="https://live.amcharts.com/lODg2/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  So what are the problems
&lt;/h4&gt;

&lt;p&gt;The first issue is that subqueries perform calculations by running through the entire table. This simply means that the query above runs through the table twice to get the results that we got. This can affect performance&lt;/p&gt;

&lt;p&gt;Another problem is that subqueries are quite difficult to read and maintain. It is quite difficult to grasp what the query above is doing at a glance&lt;/p&gt;

&lt;h3&gt;
  
  
  The window function solution
&lt;/h3&gt;

&lt;p&gt;Now let's try to solve this problem using a window function.&lt;br&gt;
The way we would do this is to replace the subquery part of the first query with our window function, like so:&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="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;countries_and_territories&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;daily_confirmed_cases&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;confirmed_today&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="n"&gt;daily_confirmed_cases&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;as&lt;/span&gt; &lt;span class="n"&gt;highest_case_recorded_in_a_day&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="nv"&gt;`bigquery-public-data.covid19_ecdc.covid_19_geographic_distribution_worldwide`&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
  &lt;span class="n"&gt;geo_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'NG'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2020-03-01'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="s1"&gt;'2020-06-01'&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;OVER()&lt;/em&gt; function is what starts our window function(as stated in the previous article in the series) while the &lt;em&gt;MAX()&lt;/em&gt; gets the maximum case recorded on a particular day in the specified time frame. &lt;/p&gt;

&lt;p&gt;The window function uses the ResultSet gotten from the WHERE part of the query thus there it does not run through the entire table like the subquery alternative. &lt;/p&gt;

&lt;p&gt;In the end, you get a much shorter, more readable, maintainable and performant code. &lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;What I have described in this article is a very simple use case of a window function. Let me know what insightful questions related to COVID-19 we could answer by comparing aggregated and unaggregated data in the comments section. &lt;/p&gt;

&lt;p&gt;Next in this series, we would be talking about performing calculations that are dependent on the value of other rows eg. running totals, daily_increase in cases etc. &lt;/p&gt;

</description>
      <category>sql</category>
      <category>datascience</category>
      <category>database</category>
      <category>googlecloud</category>
    </item>
    <item>
      <title>Watch OVER your WINDOW of opportunities</title>
      <dc:creator>Chidiebere Ogujeiofor</dc:creator>
      <pubDate>Sun, 13 Sep 2020 15:25:20 +0000</pubDate>
      <link>https://dev.to/chidioguejiofor/watch-over-your-window-of-opportunities-320l</link>
      <guid>https://dev.to/chidioguejiofor/watch-over-your-window-of-opportunities-320l</guid>
      <description>&lt;p&gt;Howdy!&lt;/p&gt;

&lt;p&gt;From the very first time I heard of SQL Window Functions, I have always been amazed at how powerful it is. Also found that a lot of folks in my circle don't really understand where or how to use it. &lt;/p&gt;

&lt;p&gt;Thus, I decided to write a series of articles that explain SQL Window functions, what they are, where they can be used etc.&lt;/p&gt;

&lt;p&gt;To make the examples more fun and easily replicable, we would be answering questions about the COVID-19 pandemic by analysing data from the &lt;a href="https://console.cloud.google.com/bigquery?_ga=2.166430526.1203821744.1596021805-162745991.1594637530"&gt;Google COVID-19 BigQuery Dataset&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In particular the &lt;code&gt;bigquery-public-data.covid19_ecdc.covid_19_geographic_distribution_worldwide&lt;/code&gt; table. &lt;/p&gt;

&lt;p&gt;Let's begin our journey by understanding some definitions.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are SQL Window Functions
&lt;/h3&gt;

&lt;p&gt;Window functions are used to perform aggregations without grouping the unaggregated data to a single row. Also, they are used to perform calculations that are relative to the current row(eg running sums/averages).&lt;/p&gt;

&lt;p&gt;A more complete definition from the PostgreSQL documentation is seen below: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A window function performs a calculation across a set of table rows that are somehow related to the current row. This is comparable to the type of calculation that can be done with an aggregate function. But unlike regular aggregate functions, use of a window function does not cause rows to become grouped into a single output row — the rows retain their separate identities. Behind the scenes, the window function is able to access more than just the current row of the query result.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  When should we use them
&lt;/h3&gt;

&lt;p&gt;I think the best way to make sense of the definition above is to look at some use cases of window functions. They come in handy when: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comparing aggregated data to unaggregated data.&lt;/li&gt;
&lt;li&gt;Performing a calculation that is dependent on the values of previous rows(eg. running totals/averages, increase of a particular value with time etc.).&lt;/li&gt;
&lt;li&gt;Ranking data.&lt;/li&gt;
&lt;li&gt;Performing calculations that involves breaking the resultSet into section(technically called 'windows').&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll take a deeper dive into these in subsequent articles in the series. For now, let's look at the basic structure of a query with a window function&lt;/p&gt;




&lt;h3&gt;
  
  
  Syntax of Window Functions
&lt;/h3&gt;

&lt;p&gt;Window functions can be created in the same way we specify columns in a SQL query. The key difference is that we use the OVER clause to specify that it is a window 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;SELECT&lt;/span&gt; 
   &lt;span class="n"&gt;_agg_func_call_&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;window_aggs&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;col_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;other_col_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;other_col_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
   &lt;span class="p"&gt;...,&lt;/span&gt;
   &lt;span class="n"&gt;other_col_n&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;_table_name_&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;other_select&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the window function is part of the SELECT statement. SQL knows that it is a window function if it has the OVER() function. &lt;/p&gt;

&lt;p&gt;The &lt;em&gt;agg_func_call&lt;/em&gt; here can be any aggregate function eg AVG, MIN, MAX, SUM, etc. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;br&gt;
One very important thing to bear in mind here is the order of operations of an SQL statement and when the Window functions are called. The order of operation is as follows&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;FROM and JOINs&lt;/li&gt;
&lt;li&gt;WHERE&lt;/li&gt;
&lt;li&gt;GROUP BY &lt;/li&gt;
&lt;li&gt;HAVING&lt;/li&gt;
&lt;li&gt;SELECT (this is when our window functions run)&lt;/li&gt;
&lt;li&gt;DISTINCT&lt;/li&gt;
&lt;li&gt;ORDER BY&lt;/li&gt;
&lt;li&gt;LIMIT/OFFSET&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thus, our Window functions can access the ResultSet after the HAVING. As we would see in subsequent articles, whenever we have to choose between a window function and a &lt;a href="https://dev.to/chidioguejiofor/sql-subqueries-in-action-2igp"&gt;Subquery&lt;/a&gt; solution, the window function would usually be faster. &lt;/p&gt;

&lt;p&gt;This is because a &lt;a href="https://dev.to/chidioguejiofor/sql-subqueries-in-action-2igp"&gt;subquery&lt;/a&gt; performs its calculation by running through the entire table while a &lt;em&gt;window function&lt;/em&gt; performs calculation with ResultSet produced from the &lt;em&gt;WHERE&lt;/em&gt; clause.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h4&gt;
  
  
  OVER function arguments
&lt;/h4&gt;

&lt;p&gt;The OVER function optionally takes some arguments&lt;br&gt;
The full syntax of the argument of the OVER() function is shown here.&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;OVER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PARTITION&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&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;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="k"&gt;ROWS&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;ROWS&lt;/span&gt; &lt;span class="k"&gt;BETWEEN&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  ORDER BY col_1, ..., col_n
&lt;/h5&gt;

&lt;p&gt;This has the same syntax as when used at the end of a SELECT statement. &lt;/p&gt;

&lt;p&gt;In the window function, however, it sorts the ResultSet which would be used in the window function. We would see examples of this later on.&lt;/p&gt;

&lt;h5&gt;
  
  
  [ROWS &lt;em&gt;rows_args&lt;/em&gt;| ROWS BETWEEN &lt;em&gt;starting_row&lt;/em&gt; BETWEEN &lt;em&gt;ending_row&lt;/em&gt;]
&lt;/h5&gt;

&lt;p&gt;This is used to perform calculations relative to the current row. It comes in very handy when performing aggregations that are relative to previous/next row values eg leading sums/averages, daily rise in cases etc.&lt;/p&gt;

&lt;h5&gt;
  
  
  PARTITION BY
&lt;/h5&gt;

&lt;p&gt;This is used to break up the data into more windows. This comes in handy in some complex calculations where we want to break up the result-set into smaller 'windows' and perform the calculations within that window. &lt;/p&gt;

&lt;p&gt;The examples of this would explain this way better than words will. &lt;/p&gt;




&lt;p&gt;So that's what you should expect in this series. I hope you have a fun read.&lt;/p&gt;

&lt;p&gt;The next on the series would be Comparing aggregated data to unaggregated data. See you there!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/hv9flxGQFN13W1T5eF/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/hv9flxGQFN13W1T5eF/giphy.gif" alt="Alt text of image"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>googlecloud</category>
      <category>covid</category>
    </item>
    <item>
      <title>Eager Loading VS Lazy Loading in SQLAlchemy</title>
      <dc:creator>Chidiebere Ogujeiofor</dc:creator>
      <pubDate>Wed, 12 Feb 2020 08:20:00 +0000</pubDate>
      <link>https://dev.to/chidioguejiofor/eager-loading-vs-lazy-loading-in-sqlalchemy-5209</link>
      <guid>https://dev.to/chidioguejiofor/eager-loading-vs-lazy-loading-in-sqlalchemy-5209</guid>
      <description>&lt;p&gt;I have heard of eager loading data relationships a lot in the past, but it was only recently that I became more conscious of it in my APIs. I will be showing you guys what it is and why you should bother about it in this post.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;The prerequisites for this post is a basic understanding of SQL Joins, SQLAlchemy and Python&lt;/p&gt;

&lt;h3&gt;
  
  
  Definitions of Eager Loading VS Lazy Loading
&lt;/h3&gt;

&lt;p&gt;Eager loading is a technique of retrieving a model's relationship data while querying the model either through a JOIN or subquery. &lt;/p&gt;

&lt;p&gt;Lazy loading, on the other hand, retrieves the related models only when an attempt is made to retrieve the relationship field by emitting SELECT statements.&lt;/p&gt;

&lt;p&gt;I think examples would help make this clearer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;Let's say we have three models, namely User, Membership and Company,  such that there is a many-to-many relationship between users and companies like so: &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%2Fres.cloudinary.com%2Fmaintenance-site%2Fimage%2Fupload%2Fv1580734509%2Farticles%2FScreenshot_2020-02-03_at_1.52.38_PM.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%2Fres.cloudinary.com%2Fmaintenance-site%2Fimage%2Fupload%2Fv1580734509%2Farticles%2FScreenshot_2020-02-03_at_1.52.38_PM.png" alt="Alt text of image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In SQLAlchemy models:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
     &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;password_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;130&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;memberships&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relationship&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Membership&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                 &lt;span class="n"&gt;back_populates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;member&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Company&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;website&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;memberships&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relationship&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Membership&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                 &lt;span class="n"&gt;back_populates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;company&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Membership&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user.id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
   &lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                               &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;company.id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
   &lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;REGULAR_USER&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;member&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relationship&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;back_populates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memberships&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relationship&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Company&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;back_populates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memberships&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  The Lazy Problem
&lt;/h3&gt;

&lt;p&gt;Now if we query a membership from our database, like so: &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;By default, SQLAlchemy retrieves only the data contained in the Membership table by running the following SQL query:&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;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sqlalchemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&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;membership&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;membership_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;membership_user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;membership_company_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;role&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;membership_role&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;
 &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Now when you try to access the &lt;code&gt;member.username&lt;/code&gt; contained in the membership object:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;it makes another DB call to retrieve the member from the User's table which then contains the username:&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;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sqlalchemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nv"&gt;"user"&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;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password_hash&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_password_hash&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;"user"&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="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;
&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sqlalchemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s1"&gt;'param_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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Similarly, when we attempt to retrieve &lt;code&gt;name&lt;/code&gt; of the &lt;code&gt;company&lt;/code&gt;, it results in another DB call:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;

&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sqlalchemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&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;company&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;company_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;website&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_website&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_address&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;company&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="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;
&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sqlalchemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s1"&gt;'param_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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;When you retrieve multiple rows(say 50) from a table using lazy loading and you run a loop to access a related field, SQLAlchemy would emit SELECT statements for each of the (50) models you retrieved.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that looping through each model described here is how marshmallow dumps nested fields to JSON. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is lazy-loading relationship fields work. You try to retrieve data only when you need them. &lt;/p&gt;
&lt;h3&gt;
  
  
  The Eager Solution
&lt;/h3&gt;

&lt;p&gt;When we Eager-Load relationship fields, we tell SQLAlchemy to retrieve those fields when the first query is being made either through a JOIN or a subquery. In general, JOINs tend to be more efficient than subqueries. &lt;/p&gt;

&lt;p&gt;We do this by using &lt;code&gt;sqlalchemy.orm&lt;/code&gt; module like so:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;orm&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;options&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joinedload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;company&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This generates the following SQL:&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;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sqlalchemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&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;membership&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;membership_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;membership_user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;membership_company_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;role&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;membership_role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_1&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;company_1_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_1_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;website&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_1_website&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_1_address&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt; &lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;OUTER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_1&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;company_1&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="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;
 &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;
&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sqlalchemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s1"&gt;'param_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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;As you can see a join is made to retrieve the &lt;code&gt;company&lt;/code&gt; relationship thus trying to access the company name&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Ade Store1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;does not lead to any extra DB call.&lt;/p&gt;
&lt;h4&gt;
  
  
  Eager Loading multiple fields
&lt;/h4&gt;

&lt;p&gt;What if we wanted to return nested data from both the &lt;code&gt;company&lt;/code&gt; and &lt;code&gt;member&lt;/code&gt; fields, how do we eager load both? We can do that easily by adding more arguments to the options method call like so:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="n"&gt;membership&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;options&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;orm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joinedload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;company&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;orm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joinedload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;member&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This generates the following SQL statement:&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;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sqlalchemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&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;membership&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;membership_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;membership_user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;membership_company_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;role&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;membership_role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_1&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;user_1_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_1_username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password_hash&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_1_password_hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_1&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;company_1_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_1_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;website&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_1_website&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_1_address&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt; &lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;OUTER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_1&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;user_1&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="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;OUTER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_1&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;company_1&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="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;
 &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;
&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sqlalchemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s1"&gt;'param_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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;With that accessing either the &lt;code&gt;company&lt;/code&gt; or &lt;code&gt;member&lt;/code&gt; field does not lead to any extra SQL statement being run.&lt;/p&gt;
&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;You should eager-load relationship fields only when you know that those fields would be used in your code else you would fall into a situation where you are retrieving values you don't actually need which can make your API a little slower. Also, be sure to avoid lazy-loading fields that you would need for your logic&lt;/p&gt;

&lt;p&gt;One other thing to note is that this concept is not tied to only SQLAlchemy. It also exists in Django ORM and some other non-python ORMs.&lt;/p&gt;

&lt;p&gt;You can get more info on this topic from the &lt;a href="https://docs.sqlalchemy.org/en/13/orm/loading_relationships.html" rel="noopener noreferrer"&gt;SQLAlchemy Docs&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I would like to end by saying that the syntax for the eager-loading doesn't quite cumbersome. You can make this easier by putting the logic in a BaseModel as I did in the blog post below&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/chidioguejiofor" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F274988%2F50ecdd87-e493-43bd-b86f-4b7fd3dfacd6.jpeg" alt="chidioguejiofor"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/chidioguejiofor/making-sqlalchemy-models-simpler-by-creating-a-basemodel-3m9c" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Simplifying SQLAlchemy models by creating a BaseModel&lt;/h2&gt;
      &lt;h3&gt;Chidiebere Ogujeiofor ・ Feb 12 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#sqlachemy&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#python&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#oop&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;Finally, you can view all the code(including setup) can be gotten the gist below:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Thanks for your time&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/26mE6Ao4osSesRpfy/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/26mE6Ao4osSesRpfy/giphy.gif" alt="Alt text of image"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>python</category>
      <category>sqlalchemy</category>
    </item>
    <item>
      <title>Simplifying SQLAlchemy models by creating a BaseModel</title>
      <dc:creator>Chidiebere Ogujeiofor</dc:creator>
      <pubDate>Wed, 12 Feb 2020 08:19:28 +0000</pubDate>
      <link>https://dev.to/chidioguejiofor/making-sqlalchemy-models-simpler-by-creating-a-basemodel-3m9c</link>
      <guid>https://dev.to/chidioguejiofor/making-sqlalchemy-models-simpler-by-creating-a-basemodel-3m9c</guid>
      <description>&lt;p&gt;SQLAlchemy's approach of making all requests a transaction and requiring you to constantly add things to the session before committing them could lead to you repeating yourself constantly. I decided to share how you can use OOP to avoid these repetitions by creating a BaseModel.&lt;/p&gt;

&lt;p&gt;Prerequisites for this is a basic understanding of SQL, SQLAlchemy and Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model Parts
&lt;/h2&gt;

&lt;p&gt;All the models in our application would most likely have the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;id&lt;/li&gt;
&lt;li&gt;created_at&lt;/li&gt;
&lt;li&gt;update_at&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, the following actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;save&lt;/li&gt;
&lt;li&gt;update&lt;/li&gt;
&lt;li&gt;bulk_create&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depending on the application we might want to add more attributes and reuseable methods to the BaseModel but this is usually a good place to start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our BaseModel
&lt;/h2&gt;

&lt;p&gt;Now let me walk through the parts of the BaseModel&lt;/p&gt;

&lt;h3&gt;
  
  
  Attributes
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;__abstract__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;__abstract__&lt;/code&gt; attribute tells &lt;em&gt;SQLAlchemy&lt;/em&gt; that this model should not be created in the database. Thus, when creating tables/migrations this class would be ignored.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&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="p"&gt;.&lt;/span&gt;
   &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;updated_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;These are the fields that would be repeating in our models. Specifying it here removes the need to add these columns when creating our models as they would be implicitly created for us.&lt;/p&gt;

&lt;p&gt;When you have time fields in your models, it is best to make them timezone sensitive. Here, I have used a lambda expression, the &lt;code&gt;datetime.timezone&lt;/code&gt; and &lt;code&gt;datetime.datetime&lt;/code&gt; classes to generate a default datetime whenever a model is saved to the database.&lt;/p&gt;
&lt;h3&gt;
  
  
  Instance Methods: Create, Update, Delete.
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&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="p"&gt;.&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;before_save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;after_save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;before_save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rollback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;after_save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;before_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;after_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;before_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;after_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;save&lt;/code&gt; method inserts the model object to the DB and rolls back when an error occurs. Since SQLAchemy performs its queries in a transaction, it rolls back all the things that have been added to this session once an error occurs. &lt;br&gt;
We can control whether we want to commit to the DB or not by specifying a value for &lt;code&gt;commit&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Although SQLAlchemy has events listeners that run &lt;em&gt;after_insert&lt;/em&gt; and &lt;em&gt;before_insert&lt;/em&gt; hooks, I have found it handy to specify these operations as methods in your model.&lt;/p&gt;

&lt;p&gt;The other methods for &lt;code&gt;update&lt;/code&gt; and &lt;code&gt;delete&lt;/code&gt; are similar&lt;/p&gt;
&lt;h3&gt;
  
  
  Class Methods: Bulk Create and Eager Loading
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Eager Loading
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&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="p"&gt;.&lt;/span&gt;
    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;eager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;cols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;orm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joinedload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;options&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;




&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Eager loading&lt;/em&gt; is a very important concept to be conscious of when querying your data. This method makes &lt;em&gt;eager loading&lt;/em&gt; easier by allowing us to just specify only the fields we want to eager load. For example&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rel1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rel2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The above call would eager-load relationships &lt;code&gt;rel1&lt;/code&gt; and &lt;code&gt;rel2&lt;/code&gt;. You can get more info about eager loading in my post&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/chidioguejiofor" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F274988%2F50ecdd87-e493-43bd-b86f-4b7fd3dfacd6.jpeg" alt="chidioguejiofor"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/chidioguejiofor/eager-loading-vs-lazy-loading-in-sqlalchemy-5209" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Eager Loading VS Lazy Loading in SQLAlchemy&lt;/h2&gt;
      &lt;h3&gt;Chidiebere Ogujeiofor ・ Feb 12 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#sql&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#python&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#sqlalchemy&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;h4&gt;
  
  
  Bulk Create
&lt;/h4&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&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="p"&gt;.&lt;/span&gt;

    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;before_bulk_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;after_bulk_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model_objs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;


    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bulk_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;before_bulk_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;model_objs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;model_objs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bulk_save_objects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_objs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;commit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;after_bulk_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_objs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;model_objs&lt;/span&gt;


    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bulk_create_or_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bulk_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntegrityError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rollback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The bulk_create implementation above allows the user to INSERT multiple rows in the database either from an array of the &lt;em&gt;model instances&lt;/em&gt; or array of &lt;em&gt;dictionaries&lt;/em&gt;. I found the &lt;em&gt;dictionaries&lt;/em&gt; part super helpful while writing automated tests.&lt;/p&gt;

&lt;p&gt;Like the save method, the &lt;em&gt;bulk_create&lt;/em&gt; method would persist to the DB when the commit &lt;code&gt;kwarg&lt;/code&gt; is set to &lt;strong&gt;True&lt;/strong&gt; and makes calls to &lt;em&gt;before_bulk_create&lt;/em&gt; and &lt;em&gt;after_bulk_create&lt;/em&gt;. It returns a list the created models on success but leaves error handling to the calling function&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;bulk_create_or_none&lt;/em&gt; differs from the &lt;em&gt;bulk_create&lt;/em&gt; by handling only &lt;em&gt;IntegrityError&lt;/em&gt;  and returning None when they occur.&lt;/p&gt;

&lt;h2&gt;
  
  
  BaseModel in use
&lt;/h2&gt;

&lt;p&gt;Here are some examples of how you can use this BaseModel&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating concrete Models
&lt;/h4&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;password_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;130&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;memberships&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relationship&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Membership&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                 &lt;span class="n"&gt;back_populates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;member&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;before_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Calling User models before_update&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;after_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Calling User models after_update&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Company&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;website&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;memberships&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relationship&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Membership&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                 &lt;span class="n"&gt;back_populates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;company&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Membership&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user.id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;company.id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;REGULAR_USER&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;member&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relationship&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;back_populates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memberships&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relationship&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Company&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;back_populates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memberships&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  INSERTING
&lt;/h4&gt;

&lt;p&gt;You can insert fields with something like:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;some_username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password_hash&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Company&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Company 1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;website&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;somewebsite.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Atom 1 close, Ojodu Lagos&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Membership&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Company&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SomeUnknownCompany&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;website&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;some.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Aguda, Surulere Lagos&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# When commit is false
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SomeUnknownCompany&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rollback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SomeUnknownCompany&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Eager Loading
&lt;/h4&gt;

&lt;p&gt;We can eager load fields:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;company&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;member&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Membership&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="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Membership&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Membership&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Membership&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Membership&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Membership&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Membership&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Membership&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Membership&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Membership&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Generating the following SQL&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;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sqlalchemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&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;membership&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;membership_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;membership_created_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;updated_at&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;membership_updated_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;membership_user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;membership_company_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;role&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;membership_role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_1&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;user_1_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_1_created_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;updated_at&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_1_updated_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_1_username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password_hash&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_1_password_hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_1&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;company_1_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_1_created_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;updated_at&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_1_updated_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_1_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;website&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_1_website&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_1_address&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;membership&lt;/span&gt; &lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;OUTER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_1&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;user_1&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="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;OUTER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;company_1&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;company_1&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="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;
&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sqlalchemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;:{}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  UPDATING
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;
&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;some_username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Adebayor1010&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;Calling&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="n"&gt;before_update&lt;/span&gt;
&lt;span class="n"&gt;Calling&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="n"&gt;after_update&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Adebayor1010&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Generating the following SQL query&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sqlalchemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nv"&gt;"user"&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;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_created_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;updated_at&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_updated_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password_hash&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_password_hash&lt;/span&gt;&lt;br&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt;&lt;br&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&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;username_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;br&gt;
&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sqlalchemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s1"&gt;'username_1'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'user1010'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Bulk Creating&lt;br&gt;
&lt;/h4&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;user_dicts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;...&lt;/span&gt;     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user1010&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password_hash&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;some_hash&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;...&lt;/span&gt;     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user1011&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password_hash&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;some_hash&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;...&lt;/span&gt;     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user1012&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password_hash&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;some_hash&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;...&lt;/span&gt;     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user1013&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password_hash&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;some_hash&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;br&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bulk_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_dicts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Conclusion&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;One small advice I have is this&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Before abstracting a particular logic to some &lt;em&gt;Base class&lt;/em&gt;, ensure that you have repeated that logic a significant amount of time. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One thing I have found myself doing is rushing into abstracting a particular logic and then realising 10 commits later that I need to edit the method in the Base class but it has been tightly coupled to &lt;em&gt;some&lt;/em&gt; concrete implementation. You can avoid falling into this by waiting until you have repeated something about 4-5 times before abstracting&lt;/p&gt;

&lt;p&gt;Hope you have fun creating your &lt;em&gt;SQLAlchemy&lt;/em&gt; models. &lt;/p&gt;

</description>
      <category>beginners</category>
      <category>sqlachemy</category>
      <category>python</category>
      <category>oop</category>
    </item>
  </channel>
</rss>
