diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 550e6e323c..e6d653a46e 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -1197,14 +1197,21 @@ class BaseQuery(object):
             col = target.column
         alias = join_list[-1]
 
+        if (lookup_type == 'isnull' and value is True and not negate and
+                len(join_list) > 1):
+            # If the comparison is against NULL, we may need to use some left
+            # outer joins when creating the join chain. This is only done when
+            # needed, as it's less efficient at the database level.
+            self.promote_alias_chain(join_list)
+
         while final > 1:
-            # An optimization: if the final join is against the same column as
-            # we are comparing against, we can go back one step in the join
-            # chain and compare against the lhs of the join instead (and then
-            # repeat the optimization). The result, potentially, involves less
-            # table joins.
+            # An optimization: if the final join is an inner join against the
+            # same column as we are comparing against, we can go back one step
+            # in the join chain and compare against the lhs of the join instead
+            # (and then repeat the optimization). The result, potentially,
+            # involves less table joins.
             join = self.alias_map[alias]
-            if col != join[RHS_JOIN_COL]:
+            if col != join[RHS_JOIN_COL] or join[JOIN_TYPE] != self.INNER:
                 break
             self.unref_alias(alias)
             alias = join[LHS_ALIAS]
@@ -1214,14 +1221,6 @@ class BaseQuery(object):
             if final == penultimate:
                 penultimate = last.pop()
 
-        if (lookup_type == 'isnull' and value is True and not negate and
-                final > 1):
-            # If the comparison is against NULL, we need to use a left outer
-            # join when connecting to the previous model. We make that
-            # adjustment here. We don't do this unless needed as it's less
-            # efficient at the database level.
-            self.promote_alias(join_list[penultimate])
-
         if connector == OR:
             # Some joins may need to be promoted when adding a new filter to a
             # disjunction. We walk the list of new joins and where it diverges
diff --git a/tests/regressiontests/null_queries/models.py b/tests/regressiontests/null_queries/models.py
index df04f14eba..7cde0aac61 100644
--- a/tests/regressiontests/null_queries/models.py
+++ b/tests/regressiontests/null_queries/models.py
@@ -13,6 +13,17 @@ class Choice(models.Model):
     def __unicode__(self):
         return u"Choice: %s in poll %s" % (self.choice, self.poll)
 
+# A set of models with an inner one pointing to two outer ones.
+class OuterA(models.Model):
+    pass
+
+class OuterB(models.Model):
+    data = models.CharField(max_length=10)
+
+class Inner(models.Model):
+    first = models.ForeignKey(OuterA)
+    second = models.ForeignKey(OuterB, null=True)
+
 __test__ = {'API_TESTS':"""
 # Regression test for the use of None as a query value. None is interpreted as
 # an SQL NULL, but only in __exact queries.
@@ -56,4 +67,16 @@ ValueError: Cannot use None as a query value
 >>> p2.choice_set.all()
 []
 
+# Querying across reverse relations and then another relation should insert
+# outer joins correctly so as not to exclude results.
+>>> obj = OuterA.objects.create()
+>>> OuterA.objects.filter(inner__second=None)
+[<OuterA: OuterA object>]
+>>> OuterA.objects.filter(inner__second__data=None)
+[<OuterA: OuterA object>]
+>>> _ = Inner.objects.create(first=obj)
+>>> Inner.objects.filter(first__inner__second=None)
+[<Inner: Inner object>]
+
+
 """}
diff --git a/tests/regressiontests/one_to_one_regress/models.py b/tests/regressiontests/one_to_one_regress/models.py
index 66d00d7223..5c89c55f45 100644
--- a/tests/regressiontests/one_to_one_regress/models.py
+++ b/tests/regressiontests/one_to_one_regress/models.py
@@ -33,6 +33,15 @@ class Favorites(models.Model):
     def __unicode__(self):
         return u"Favorites for %s" % self.name
 
+class Target(models.Model):
+    pass
+
+class Pointer(models.Model):
+    other = models.OneToOneField(Target, primary_key=True)
+
+class Pointer2(models.Model):
+    other = models.OneToOneField(Target)
+
 __test__ = {'API_TESTS':"""
 # Regression test for #1064 and #1506: Check that we create models via the m2m
 # relation if the remote model has a OneToOneField.
@@ -119,4 +128,17 @@ False
 >>> r.place == p
 True
 
+# Regression test for #9968: filtering reverse one-to-one relations with
+# primary_key=True was misbehaving. We test both (primary_key=True & False)
+# cases here to prevent any reappearance of the problem.
+>>> _ = Target.objects.create()
+>>> Target.objects.filter(pointer=None)
+[<Target: Target object>]
+>>> Target.objects.exclude(pointer=None)
+[]
+>>> Target.objects.filter(pointer2=None)
+[<Target: Target object>]
+>>> Target.objects.exclude(pointer2=None)
+[]
+
 """}