Index: django/db/models/sql/query.py
===================================================================
--- django/db/models/sql/query.py	(revision 12831)
+++ django/db/models/sql/query.py	(working copy)
@@ -407,6 +407,8 @@
             "Cannot combine a unique query with a non-unique query."
 
         self.remove_inherited_models()
+        l_tables = set([a for a in self.tables if self.alias_refcount[a]])
+        r_tables = set([a for a in rhs.tables if rhs.alias_refcount[a]])
         # Work out how to relabel the rhs aliases, if necessary.
         change_map = {}
         used = set()
@@ -424,13 +426,19 @@
             first = False
 
         # So that we don't exclude valid results in an "or" query combination,
-        # the first join that is exclusive to the lhs (self) must be converted
+        # all joins exclusive to either the lhs or the rhs must be converted
         # to an outer join.
         if not conjunction:
-            for alias in self.tables[1:]:
-                if self.alias_refcount[alias] == 1:
-                    self.promote_alias(alias, True)
-                    break
+            # Update r_tables aliases.
+            for alias in change_map:
+                if alias in r_tables:
+                    r_tables.remove(alias)
+                    r_tables.add(change_map[alias])
+            # Find aliases that are exclusive to rhs or lhs.
+            # These are promoted to outer joins.
+            outer_aliases = (l_tables | r_tables) - (l_tables & r_tables)
+            for alias in outer_aliases:
+                self.promote_alias(alias, True)
 
         # Now relabel a copy of the rhs where-clause and add it to the current
         # one.
Index: tests/regressiontests/queries/tests.py
===================================================================
--- tests/regressiontests/queries/tests.py	(revision 12831)
+++ tests/regressiontests/queries/tests.py	(working copy)
@@ -1,6 +1,6 @@
 import unittest
-from models import Tag, Annotation
-from django.db.models import Count
+from models import Tag, Annotation, ObjectA, ObjectB, ObjectC
+from django.db.models import Count, Q
 
 class QuerysetOrderedTests(unittest.TestCase):
     """
@@ -24,4 +24,71 @@
         qs = Annotation.objects.annotate(num_notes=Count('notes'))
         self.assertEqual(qs.ordered, False)
         self.assertEqual(qs.order_by('num_notes').ordered, True)
-        
\ No newline at end of file
+
+
+class UnionTests(unittest.TestCase):
+    """
+    Tests for the union of two querysets.
+    Bug #12252.
+    """
+    
+    def __init__(self, *args, **kwargs):
+        super(UnionTests, self).__init__(*args, **kwargs)
+
+    def setUp(self):
+        # Don't bother setting up if already done
+        if ObjectA.objects.all():
+            return
+        objectas = []
+        objectbs = []
+        objectcs = []
+        a_info = ['one', 'two', 'three']
+        for name in a_info:
+            o = ObjectA(name=name)
+            o.save()
+            objectas.append(o)
+        b_info = [('un', 1, objectas[0]), ('deux', 2, objectas[0]), ('trois', 3, objectas[2])]
+        for name, number, objecta in b_info:
+            o = ObjectB(name=name, number=number, objecta=objecta)
+            o.save()
+            objectbs.append(o)
+        c_info = [('ein', objectas[2], objectbs[2]), ('zwei', objectas[1], objectbs[1])]
+        for name, objecta, objectb in c_info:
+            o = ObjectC(name=name, objecta=objecta, objectb=objectb)
+            o.save()
+            objectcs.append(o)
+
+    def check_union(self, model, Q1, Q2):
+        filter = model.objects.filter
+        self.assertEqual(set(filter(Q1) | filter(Q2)), set(filter(Q1 | Q2)))
+        self.assertEqual(set(filter(Q2) | filter(Q1)), set(filter(Q1 | Q2)))
+        
+    def test_A_AB(self):
+        Q1 = Q(name='two')
+        Q2 = Q(objectb__name='deux')
+        self.check_union(ObjectA, Q1, Q2)
+        
+    def test_A_AB2(self):
+        Q1 = Q(name='two')
+        Q2 = Q(objectb__name='deux', objectb__number=2)
+        self.check_union(ObjectA, Q1, Q2)
+
+    def test_AB_ACB(self):
+        Q1 = Q(objectb__name='deux')
+        Q2 = Q(objectc__objectb__name='deux')
+        self.check_union(ObjectA, Q1, Q2)
+
+    def test_BAB_BAC(self):
+        Q1 = Q(objecta__objectb__name='deux')
+        Q2 = Q(objecta__objectc__name='ein')
+        self.check_union(ObjectB, Q1, Q2)
+        
+    def test_BAB_BACB(self):
+        Q1 = Q(objecta__objectb__name='deux')
+        Q2 = Q(objecta__objectc__objectb__name='trois')
+        self.check_union(ObjectB, Q1, Q2)
+
+    def test_BA_BCA__BAB_BAC_BCA(self):
+        Q1 = Q(objecta__name='one', objectc__objecta__name='two')
+        Q2 = Q(objecta__objectc__name='ein', objectc__objecta__name='three', objecta__objectb__name='trois')
+        self.check_union(ObjectB, Q1, Q2)
Index: tests/regressiontests/queries/models.py
===================================================================
--- tests/regressiontests/queries/models.py	(revision 12831)
+++ tests/regressiontests/queries/models.py	(working copy)
@@ -275,7 +275,30 @@
     def __unicode__(self):
         return self.name
 
+# Bug #12252
+class ObjectA(models.Model):
+    name = models.CharField(max_length=50)
 
+    def __unicode__(self):
+        return self.name
+
+class ObjectB(models.Model):
+    name = models.CharField(max_length=50)
+    objecta = models.ForeignKey(ObjectA)
+    number = models.PositiveSmallIntegerField()
+
+    def __unicode__(self):
+        return self.name
+
+class ObjectC(models.Model):
+    name = models.CharField(max_length=50)
+    objecta = models.ForeignKey(ObjectA)
+    objectb = models.ForeignKey(ObjectB)
+
+    def __unicode__(self):
+        return self.name
+
+
 __test__ = {'API_TESTS':"""
 >>> # Regression for #13156 -- exists() queries have minimal SQL
 >>> from django.db import connection
