<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="351656" data-post-id="351656">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="waseigo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/waseigo/120/34129_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  waseigo
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hello everyone and Happy New Year!</p>
<p>I hope that 2025 finds you healthy and personally and professionally fulfilled, and ideally with more Elixir coding than in other programming languages <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p>As <strong>Northwind Elixir Traders</strong> is nearing completion, I have reworked the first 12 chapters, fixed various typos, added clarifications, and improved the wording in a few sections. The PDF file is now generated with a new theme and a smaller (and more consistent) font size that affords more space for code on each page.</p>
<p>The latest version includes <strong>Chapter 13</strong> on tying some loose ends created by an oversimplified prioritization algorithm in an earlier chapter, for determining the order of importing (or tearing down) tables with the <code>DataImporter</code> module’s functions. Though not central to working with databases, we debug and fix the <code>prioritize/0</code> function by reimplementing it with a Depth-First Search algorithm on the following graph of dependencies between the tables of the ERD of Northwind Traders:</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://forum.elixirforum.com/uploads/default/original/3X/0/b/0b65e3f000675b0b550e75da8d4c85d15506f384.jpeg" data-download-href="https://forum.elixirforum.com/uploads/default/0b65e3f000675b0b550e75da8d4c85d15506f384" title="nt_erd_inverted_tree" rel="nofollow"><img src="https://forum.elixirforum.com/uploads/default/optimized/3X/0/b/0b65e3f000675b0b550e75da8d4c85d15506f384_2_690x222.jpeg" alt="nt_erd_inverted_tree" data-base62-sha1="1CPybepWskIVbyq4W6i2HaLvICE" width="690" height="222" srcset="https://forum.elixirforum.com/uploads/default/optimized/3X/0/b/0b65e3f000675b0b550e75da8d4c85d15506f384_2_690x222.jpeg, https://forum.elixirforum.com/uploads/default/optimized/3X/0/b/0b65e3f000675b0b550e75da8d4c85d15506f384_2_1035x333.jpeg 1.5x, https://forum.elixirforum.com/uploads/default/optimized/3X/0/b/0b65e3f000675b0b550e75da8d4c85d15506f384_2_1380x444.jpeg 2x" data-dominant-color="F7F8FA"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">nt_erd_inverted_tree</span><span class="informations">2695×870 94.4 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><p></p>
<p>The next chapter drops within the next week and will be covering Ecto queries.</p>
<p>Until then, cheers from Greece,<br>
Isaak</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="351656" data-batch-url="/posts/batch_likers">
                        7
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/northwind-elixir-traders-pragprog/70887/32">Post #31</a>
	                </div>
	            </div>
              <div id="likers-container-351656" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="351656"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #31"></div>
  </section>
</div>
    <div class="postbit" id="352797" data-post-id="352797">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="waseigo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/waseigo/120/34129_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  waseigo
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p><strong>Chapter 14</strong> on Ecto queries on the Northwind Traders toy dataset is dropping very soon within the week, possibly within the next 24 hours.</p>
<p>It is about Ecto queries primarily, but also includes sidequests on parallelization of queries (without a significant benefit, since we’re IO-bound), and dealing with money amounts (the type of the <code>:price</code>  field was deliberately set as <code>:float</code> in the definition <code>%Product{}</code> schema many chapters ago and you can imagine what happens when we use floats in calculations of, e.g. the total value of an Order). It also includes some more insights about development (waterfall, agile, the sane middle ground, and a few other hints from my experience), and some experience-derived parts on what kinds of queries tend to be useful for a business like the fictional Northwind Elixir Traders aiming to grow its revenues.</p>
<p>Here’s an outtake of the development process <img src="https://forum.elixirforum.com/images/emoji/apple/laughing.png?v=15" title=":laughing:" class="emoji" alt=":laughing:" loading="lazy" width="20" height="20">, which has been kitten-assisted as of ~4 weeks ago. (Kindly do ignore the mouspad and all the garish RGB lights…)</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://forum.elixirforum.com/uploads/default/original/3X/5/3/53ad3013568e56b8371acc924e952cb36a3f5f31.jpeg" data-download-href="https://forum.elixirforum.com/uploads/default/53ad3013568e56b8371acc924e952cb36a3f5f31" title="image" rel="nofollow"><img src="https://forum.elixirforum.com/uploads/default/optimized/3X/5/3/53ad3013568e56b8371acc924e952cb36a3f5f31_2_690x318.jpeg" alt="image" data-base62-sha1="bWeGmazP8yPGI68XBZ7bSXMyZUt" width="690" height="318" srcset="https://forum.elixirforum.com/uploads/default/optimized/3X/5/3/53ad3013568e56b8371acc924e952cb36a3f5f31_2_690x318.jpeg, https://forum.elixirforum.com/uploads/default/optimized/3X/5/3/53ad3013568e56b8371acc924e952cb36a3f5f31_2_1035x477.jpeg 1.5x, https://forum.elixirforum.com/uploads/default/original/3X/5/3/53ad3013568e56b8371acc924e952cb36a3f5f31.jpeg 2x" data-dominant-color="55494A"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">image</span><span class="informations">1200×554 73.7 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><p></p>
<p>After Chapter 14, there is not much more left to discuss. The last couple of chapters will investigate whether our application still works if we switch from SQLite to Postgres, and some ideas for taking this project further.</p>
<p>Stay tuned!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="352797" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/northwind-elixir-traders-pragprog/70887/33">Post #32</a>
	                </div>
	            </div>
              <div id="likers-container-352797" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="352797"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #32"></div>
  </section>
</div>
    <div class="postbit" id="353375" data-post-id="353375">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="waseigo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/waseigo/120/34129_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  waseigo
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hello readers both current and prospective,</p>
<p><a href="https://leanpub.com/b/lo-and-behold-x-1-to-5" rel="noopener nofollow ugc">Lo and behold</a>, I bring you sweet tidings of great progress!</p>
<p><em>Northwind Elixir Traders</em> is practically completed in terms of content–I am currently working on QA of chapters 15 and 16, but everything else is done. I expect my QA to conclude within the next couple of days.</p>
<p>These two remaining short chapters will cover queries with window functions, as well as some leftovers, such as using <code>Ecto.Enum</code>, redacting fields with sensitive data, modeling one-to-one associations, and finally checking whether the application also works with Postgres instead of SQLite.</p>
<p>The biggest change since the last update is Chapter 14 on queries. Like a few other chapters before, this too had a big sidequest: dealing with the consequences of the price being originally modeled as a <code>:float</code> in the Ecto schema of the <code>%Product{}</code>.  After investigating what this causes when we calculate aggregate values of orders’ revenues, we use SQL in a migration to convert the dollar prices to cents and another migration to change the field type to <code>:integer</code>.</p>
<p>We learn to build increasingly complex queries with both <code>join: ...</code> and <code>left_join: ...</code>, and use <code>group_by</code> and <code>order_by</code> to build subqueries and dynamic queries. All this allows us to calculate the different entities’ (<code>Customer</code>, <code>Product</code>, <code>Category</code>, <code>Employee</code>, etc.) share of revenues, also in a cumulative manner. Thus, we even manage to calculate the Gini coefficient of such data pairings!</p>
<p>Besides that, we explore Elixir’s parallel execution capabilities using the <code>Task</code> module, and the pointlessness of running I/O-bound queries in parallel. We also iteratively refactor the new <code>Insights</code> module’s function, so that our queries are composable. Throughout the chapter we run numerous queries to derive insights and, not leaving the context of the application behind, we also discuss what could motivate the implementation of such queries we write.</p>
<p>There is now also a Chapter 17 with ideas for where you could take the application with improvements and extensions to the database and the Elixir code.</p>
<p>Thank you to the many readers who gave this book a shot since its infancy in April 2024, and especially to all those who provided feedback. Without your patronage, this book would not have grown to 300+ pages over almost a year!</p>
<p>Once again, if you particularly enjoyed the book and would like to contribute a testimonial for the Leanpub page, email me or connect with me on LinkedIn. My contact details are in the book.</p>
<p>Enjoy Chapter 14, and until very soon again,<br>
Isaak</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="353375" data-batch-url="/posts/batch_likers">
                        4
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/northwind-elixir-traders-pragprog/70887/34">Post #33</a>
	                </div>
	            </div>
              <div id="likers-container-353375" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="353375"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #33"></div>
  </section>
</div>
    <div class="postbit" id="356827" data-post-id="356827">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="waseigo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/waseigo/120/34129_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  waseigo
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hello there database admins of the Northwind Elixir Traders business,</p>
<p>It’s been a while since the last update–the reason is that <strong>Chapter 15</strong> seriously kicked my butt. I got stuck trying to make dynamic queries with positional bindings and scrapped half the chapter before I found a way to converge towards window queries with named bindings.</p>
<p>The great news is that the book is nearing completion. What’s still missing?</p>
<ol>
<li>
<p>Implementing a rolling-window query that uses an SQL fragment with <code>RANGE</code> over order dates instead of <code>ROWS</code> over… rows. I kicked this to Chapter 16, as Chapter 15 became enormous, and I saw that this query will need its own chapter, due to the limitations of SQLite (it doesn’t support <code>INTERVAL</code>).</p>
</li>
<li>
<p>Chapter 17 with the leftover bits and pieces that are not necessary for modeling Northwind Traders, but nevertheless good to know (<code>Ecto.Enum</code> for statuses, one-to-one associations, and redacting fields with sensitive data to help stay GDPR-compliant), plus a temporary switch to Postgres to see that everything should still work without any other changes.</p>
</li>
</ol>
<p>Chapter 15 brings a ton of content, including:</p>
<ul>
<li>“automatic” joins across the ERD (automatic only after a lot of manual work) that make named bindings available for downstream queries and partitioning by up to two schemas’ IDs,</li>
<li>queries that use <code>dynamic/2</code>,</li>
<li>an exploration of queries with group_by as a “degraded” version of queries with partitioning,</li>
<li>window queries for the running total of revenues for the entire dataset and by schema,</li>
<li>sliding-window queries for the rolling average (and min, max, and sum) of the entire dataset and partitioned by two schemas, and</li>
<li>disaggregation function to turn the partitioned output into consumer-friendly maps, and</li>
<li>for these window queries, selectable aggregate functions and optional date filters, also with support for year or year-month combinations, so that e.g. display on a web UI becomes easier.</li>
</ul>
<p>As the book is nearing completion, I have reviewed the entire book and fixed typos, as well as 1 function that I was referring to in the text, but had neglected to copy over from the codebase (thank you Benjamin!) There is now also an index of figures with clickable links to all functions implemented throughout.</p>
<p>Furthermore, I have improved formatting so that the code on the pages is more dense, unnecessary IEx output is hidden or wrapped, and formulas entered in IEx are copy-pasteable into your terminal without selecting “\” characters that were being introduced by pandoc to wrap lines.</p>
<p>I am confident that I can bring you the 100% completed book by end of February.</p>
<p>Once the book is finished, I will mirror my git repository of the codebase to a public Github repository under the Apache-2.0 license. Also, I will go through all pages and hyperlink every mention to an Elixir function to the relevant documentation page, so that you can easily refer to the functions while you learn, and perhaps play around with the functions’ <code>opts</code>.</p>
<p>Thank you for supporting the book while still in development. If you are open to writing a testimonial for the inside of the book, its landing page, and wherever else it will be published (wink wink nudge nudge), please email me at <a href="mailto:isaak@overbring.com" rel="nofollow">isaak@overbring.com</a>.</p>
<p>That’s all for now–expect to receive one or two more updates within the next 10 days.</p>
<p>Cheers from Athens,<br>
Isaak</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356827" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/northwind-elixir-traders-pragprog/70887/35">Post #34</a>
	                </div>
	            </div>
              <div id="likers-container-356827" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356827"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #34"></div>
  </section>
</div>
    <div class="postbit" id="358506" data-post-id="358506">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="waseigo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/waseigo/120/34129_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  waseigo
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hello everyone,</p>
<p>A new release of the book has just been published. Here’s what has changed in the last 16 days:</p>
<ul>
<li>Chapters 14 and 15 have been rewritten almost from scratch, following reader feedback. The resulting functions are now way more composable, and the logic behind their gradual development and “stacking” has been made more clear.</li>
<li>Some parts of Chapter 15 were moved to 14, where they were needed earlier, also to avoid rework in 15, and to make the build-up towards composable window queries more straightforward.</li>
<li>Everything until and including Chapter 15 has been “replayed”. This includes all IEx code snippets, and all migrations, modules, functions and changes made throughout.</li>
<li>As I’ve been replaying all chapters so far, I’ve been building a local git repository from scratch. Every change to the codebase is shown in a figure, and every figure and every small change corresponds to a commit.</li>
<li>Once Chapters 16 and 17 are completed and quality-assured, the git repo will be made public on GitHub and licensed under Apache-2.0. I will also see how feasible it is to link every figure to the corresponding git commit.</li>
<li>Almost all Elixir function names are now hyperlinked to their corresponding online documentation. Any remaining stragglers will be fixed until 100% completion.</li>
<li>I started using <code>hunspell -d en_US</code> on all Markdown source files, so there should now be no (or close to no) spelling mistakes left.</li>
<li>The PDF is now 461 pages long (actual content: 453 pages). It includes so many side-quests and explorations of Elixir features besides Ecto that I’m considering changing the subtitle to “Learn Elixir and how to model databases with Ecto and SQLite in one fell swoop” or so. For sure, if you enter this book with basic knowledge of Elixir, you come out way stronger out of it.</li>
</ul>
<p>As somewhat of a perfectionist, I wouldn’t let Chapters 14 and 15 stand as they were, but this has delayed work on Chapter 16. I’m resuming work on it tomorrow. It’s expected to be a tough one, as it involves writing CTEs to deal with SQLite’s missing support for <code>INTERVAL</code>. Let’s see if I can finish within the coming week. In this release I’ve also included the first few pages of that chapter.</p>
<p>Thank you all for your patience, feedback, and patronage–it has all made this book something that I could never envision when I started working on it around a year ago!</p>
<p>Cheers from Athens, Greece,<br>
Isaak</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="358506" data-batch-url="/posts/batch_likers">
                        4
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/northwind-elixir-traders-pragprog/70887/36">Post #35</a>
	                </div>
	            </div>
              <div id="likers-container-358506" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="358506"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #35"></div>
  </section>
</div>
    <div class="postbit" id="358513" data-post-id="358513">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="arcanemachine" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/arcanemachine/120/29109_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  arcanemachine
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>What a changelog. I admire your dedication to this work.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="358513" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/northwind-elixir-traders-pragprog/70887/37">Post #36</a>
	                </div>
	            </div>
              <div id="likers-container-358513" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="358513"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #36"></div>
  </section>
</div>
    <div class="postbit" id="358538" data-post-id="358538">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="waseigo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/waseigo/120/34129_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  waseigo
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>This is the kind of feedback that makes this kind of dedication manifest <img src="https://forum.elixirforum.com/images/emoji/apple/grin.png?v=15" title=":grin:" class="emoji" alt=":grin:" loading="lazy" width="20" height="20"> Thank you!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="358538" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/northwind-elixir-traders-pragprog/70887/38">Post #37</a>
	                </div>
	            </div>
              <div id="likers-container-358538" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="358538"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #37"></div>
  </section>
</div>
    <div class="postbit" id="359048" data-post-id="359048">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="waseigo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/waseigo/120/34129_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  waseigo
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hello and welcome to <strong>version 1.0 of Northwind Elixir Traders</strong> – now with a new subtitle!</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://forum.elixirforum.com/uploads/default/original/3X/f/5/f54936eb7cb2733f683a611ff78bb84f845675e7.jpeg" data-download-href="https://forum.elixirforum.com/uploads/default/f54936eb7cb2733f683a611ff78bb84f845675e7" title="northwind-elixir-traders-cover" rel="nofollow"><img src="https://forum.elixirforum.com/uploads/default/original/3X/f/5/f54936eb7cb2733f683a611ff78bb84f845675e7.jpeg" alt="northwind-elixir-traders-cover" data-base62-sha1="yZTQbndDqdqVFqSq4i4Kds6YjT9" width="463" height="600"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">northwind-elixir-traders-cover</span><span class="informations">500×647 37.7 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><p></p>
<p>Since the last update:</p>
<ul>
<li><strong>Chapter 16</strong> was written from scratch. We now have complex (complicated) queries that use Common Table Expressions and <code>ROWS</code> in a window fragment to perform window-aggregate calculations for rolling and running (sliding and expanding) windows across sequential and unique dates of dataset with triple partitioning–<em>even for those dates that have no orders</em>. There is also a lot of exploration of SQLite’s troubles with complex queries of that kind, as well as a section on profiling database queries with SQLite’s <code>EXPLAIN QUERY PLAN</code> (and with Elixir and Erlang’s <code>:timer</code> module) to determine what’s causing them to run slow.</li>
<li><strong>Chapter 17</strong> (<em>“Leftover bits and pieces”</em>) was dropped, since it seemed too “poor”, especially for a closing chapter. After reviewing the book in its entirety, I concluded that everything that was supposed to be in there was either truly trivial (<code>Ecto.Enum</code>, redacting fields, and one-to-one associations) compared to what the book has covered in almost 500 pages, or was always truly beyond the scope of the book (switching to PostgreSQL, which shouldn’t pose an issue given how everything has been implemented).</li>
<li>With a handful of exceptions, now <strong>all</strong> Elixir, Ecto and SQLite functions have been hyperlinked to their online documentation. I considered hyperlinking the book contents to the git commits, but after trying it out I found that it made already-busy book pages even busier, hindering readability.</li>
</ul>
<p>With this, <strong>the book is now 100% complete!</strong></p>
<p>For those of who have have been asking me for the complete codebase, it’s now available and Apache-2.0 licensed: <a href="https://github.com/waseigo/northwind_elixir_traders" class="inline-onebox" rel="noopener nofollow ugc">GitHub - waseigo/northwind_elixir_traders: The official repository of the "Northwind Elixir Traders" book · GitHub</a>. Every code block and every instruction to change something to the code corresponds to a git commit. The commit title is the title of the corresponding code block, or a snippet of the text with the instruction on what to change/remove.</p>
<p>The entirety of the book has now been “replayed”–that’s how the git repo has been built from scratch by following the book step by step. Still, to err is human, so should you get stuck anywhere, please let me know.</p>
<p>Thank you again for your patronage and for those of you who have contributed comments and suggestions, asked questions, and requested clarifications. It has made the book way better than I ever imagined!</p>
<p>The next step in the story of this book is the upcoming episode of the Elixir Mentor podcast (<a href="https://elixirmentor.com/podcast" class="inline-onebox" rel="noopener nofollow ugc">Podcast · Elixir Mentor</a>) with Jacob Luetzow (<a href="https://forum.elixirforum.com/u/jacobluetzow" rel="nofollow">jacobluetzow</a>). We’ll record it on March 21st.</p>
<p>The next step for me, Elixir, and writing technical books is the upcoming and much shorter <a href="https://leanpub.com/elixir-chatbot-alchemy" rel="noopener nofollow ugc"><strong>Elixir Chatbot Alchemy</strong></a>, in which we will follow a similar exploratory approach to develop a self-hosted chatbot with Elixir, the Ollama REST API, Ecto, and Phoenix LiveView under the severe constraint of getting a decent chatbot working with only CPU-based inference.</p>
<p>If you enjoyed the book (or even if you didn’t!), drop me an email or contact me here–I look forward to hearing what you liked, what you didn’t, and anything else you’d like to share!</p>
<p>Best regards,<br>
Isaak</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="359048" data-batch-url="/posts/batch_likers">
                        13
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/northwind-elixir-traders-pragprog/70887/39">Post #38</a>
	                </div>
	            </div>
              <div id="likers-container-359048" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="359048"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-most-liked cat-most-liked" title="One of the top 3 liked posts in this thread!"></div>
  </section>
</div>
    <div class="postbit" id="359110" data-post-id="359110">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="warmwaffles" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/warmwaffles/120/22057_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  warmwaffles
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="waseigo" data-post="39" data-topic="70887">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/waseigo/48/34129_2.png" class="avatar"> waseigo:</div>
<blockquote>
<p>Ecto and SQLite</p>
</blockquote>
</aside>
<p>Awesome to see this gaining more popularity.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="359110" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/northwind-elixir-traders-pragprog/70887/40">Post #39</a>
	                </div>
	            </div>
              <div id="likers-container-359110" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="359110"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #39"></div>
  </section>
</div>
    <div class="postbit" id="359206" data-post-id="359206">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="waseigo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/waseigo/120/34129_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  waseigo
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thank you for Ecto SQLite3!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="359206" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/northwind-elixir-traders-pragprog/70887/41">Post #40</a>
	                </div>
	            </div>
              <div id="likers-container-359206" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="359206"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #40"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/70887/load_more?page=5">Load more posts (37 remaining)</a>
</div></template></turbo-stream>