<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>

CC BY-SA 4.0
2019-01-23T11:59:25.127Z
2019-01-23T11:59:25.127Z
Oli
<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>

<plugin-development><craft3><elementquery>
Checking if user authored an entry in another channel while in loop, N+1 problem
# 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 :)


---

