Answers.Body: <p>There's one bit missing in the constrains you explain above, do users end up with 1 entry <strong>only</strong> per channel so a total of 2 posts max?</p>
  
  <p>If so, we know that:</p>
  
  <ul>
  <li>each users can have a max of 2 posts</li>
  <li>a user cannot post in B is they haven't completed their post in A</li>
  </ul>
  
  <p>So assuming this first condition is also true (2 entries/user) you could just loop through users post count looking for those with less than 2 posts and they would automatically be the users who haven't posted in B..? Just a shot in the dark :)</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-01-23T11:59:25.127Z
Answers.LastActivityDate: 2019-01-23T11:59:25.127Z
Answers.UserDisplayName: Oli
Body: <p>I have 2 channels set up: <strong>Channel A</strong> and <strong>Channel B</strong>.  I also have public registration so users can log in and fill out two forms (<strong>Form A</strong> and <strong>Form B</strong>), each form creating an entry in their respective channel with the user as the author.  The user can only create an entry in Channel B if they already have an entry in Channel A.</p>
  
  <p>To get all the users who have an entry in Channel A but not in Channel B, I tried writing something like this in my class:</p>
  
  <pre><code>public function getUsersWithoutChannelBEntry()
  {
      $channel_A_entries = Entry::find()
          -&gt;sectionId(1)
          -&gt;all();
  
      $userIds = [];
      foreach ($channel_A_entries as $entry) {
  
          $channel_B_entry_exists = Entry::find()
              -&gt;sectionId(2)
              -&gt;authorId($entry-&gt;authorId)
              -&gt;exists();
  
          if (! $channel_B_entry_exists) {
              $userIds[] = $entry-&gt;authorId;
          }
  
      }
  
      return User::find()
          -&gt;id($userIds)
          -&gt;all();
  }
  </code></pre>
  
  <p>However, this creates an N+1 problem. I have roughly 200 users, so potentially 200 entries in either channel, and thus a lot of db queries and a substantially larger load time.</p>
  
  <p>As an alternative approach, I've also tried looping through Channel A, adding each author ID into an array (Array A), then doing the same with Channel B making Array B.  Then I use <code>array_diff()</code> to extract the author IDs that are in Array A but not in Array B.  However, this still causes a bit of long load time.</p>
  
  <p>I've looked into eager loading, but that seems to only apply to related fields.</p>
  
  <p>Is there a more efficient way to get all users who authored a Channel A entry but not Channel B entry?</p>
  
Tags: <plugin-development><craft3><elementquery>
Title: Checking if user authored an entry in another channel while in loop, N+1 problem
ThreadText: # Checking if user authored an entry in another channel while in loop, N+1 problem
  
  (Asked by: username_0 on 2019-01-22)
  
  I have 2 channels set up: **Channel A** and **Channel B**. I also have public registration so users can log in and fill out two forms (**Form A** and **Form B**), each form creating an entry in their respective channel with the user as the author. The user can only create an entry in Channel B if they already have an entry in Channel A.
  
  To get all the users who have an entry in Channel A but not in Channel B, I tried writing something like this in my class:
  
  ```
  public function getUsersWithoutChannelBEntry()
  {
      $channel_A_entries = Entry::find()
          ->sectionId(1)
          ->all();
  
      $userIds = [];
      foreach ($channel_A_entries as $entry) {
  
          $channel_B_entry_exists = Entry::find()
              ->sectionId(2)
              ->authorId($entry->authorId)
              ->exists();
  
          if (! $channel_B_entry_exists) {
              $userIds[] = $entry->authorId;
          }
  
      }
  
      return User::find()
          ->id($userIds)
          ->all();
  }
  
  ```
  
  However, this creates an N+1 problem. I have roughly 200 users, so potentially 200 entries in either channel, and thus a lot of db queries and a substantially larger load time.
  
  As an alternative approach, I've also tried looping through Channel A, adding each author ID into an array (Array A), then doing the same with Channel B making Array B. Then I use `array_diff()` to extract the author IDs that are in Array A but not in Array B. However, this still causes a bit of long load time.
  
  I've looked into eager loading, but that seems to only apply to related fields.
  
  Is there a more efficient way to get all users who authored a Channel A entry but not Channel B entry?
  
  **Tags:** plugin-development, craft3, elementquery
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2019-01-23. Score: 1
  
  There's one bit missing in the constrains you explain above, do users end up with 1 entry **only** per channel so a total of 2 posts max?
  
  If so, we know that:
  
  * each users can have a max of 2 posts
  * a user cannot post in B is they haven't completed their post in A
  
  So assuming this first condition is also true (2 entries/user) you could just loop through users post count looking for those with less than 2 posts and they would automatically be the users who haven't posted in B..? Just a shot in the dark :)
  
  
  ---
  
  