在SQL查询中结合UNION和JOIN
我有以下Django型号:在SQL查询中结合UNION和JOIN,sql,postgresql,join,union,Sql,Postgresql,Join,Union,我有以下Django型号: class Person(models.Model): name = models.CharField(max_length=50) class Pet(models.Model): name = models.CharField(max_length=50) class Change(models.Model): table_name = models.CharField(max_length=50) record_id = mo
class Person(models.Model):
name = models.CharField(max_length=50)
class Pet(models.Model):
name = models.CharField(max_length=50)
class Change(models.Model):
table_name = models.CharField(max_length=50)
record_id = models.IntegerField()
workspace_id = models.IntegerField(null=True)
我可以使用以下脚本将一些数据加载到数据库中:
p1, _ = Person.objects.get_or_create(name="Person1")
_p1, _ = Person.objects.get_or_create(name="Person1.DRAFT")
p2, _ = Person.objects.get_or_create(name="Person2")
_p2, _ = Person.objects.get_or_create(name="Person2.DRAFT")
p3, _ = Person.objects.get_or_create(name="Person3")
t1, _ = Pet.objects.get_or_create(name="Pet1")
t2, _ = Pet.objects.get_or_create(name="Pet2")
c1, _ = Change.objects.get_or_create(table_name="Person", record_id=_p1.pk, workspace_id=1)
c2, _ = Change.objects.get_or_create(table_name="Person", record_id=_p2.pk, workspace_id=2)
我可以编写一个查询来堆叠所有Person
和Pet
行。使用操作员可以轻松完成以下操作:
SELECT 'Person' as type, t.id, t.name FROM union_person t
UNION
SELECT 'Pet' as type, t.id, t.name FROM union_pet t;
这将生成以下结果:
| type | id | name |
| :----- | :-- | :------------ |
| Person | 1 | Person1 |
| Person | 2 | Person1.DRAFT |
| Person | 3 | Person2 |
| Person | 4 | Person2.DRAFT |
| Person | 5 | Person3 |
| Pet | 1 | Pet1 |
| Pet | 2 | Pet2 |
现在,我的目标是通过与Change
表的连接添加workspace\u id
列。我想要的表应该是这样的(与上面的表完全相同,只是添加了workspace\u id
值,如果它们存在的话):
这是我必须实现的查询:
SELECT 'Person' as type, t.id, t.name, c.workspace_id FROM union_person t
LEFT JOIN union_change c on t.id = c.record_id and 'Person' = c.table_name
UNION
SELECT 'Pet' as type, t.id, t.name, c.workspace_id FROM union_pet t
LEFT JOIN union_change c on t.id = c.record_id and 'Pet' = c.table_name;
这是最好的解决方案还是有更好的解决方案
注意:我需要这个查询来创建一个,它将用于搜索整个数据库。这看起来是一个合理的解决方案。看起来您正在其他地方执行联合,我想知道不这样做,而是执行与基础数据的外部连接是否有好处。您可以使用
union ALL
,它不尝试删除重复项(您不能),因此速度有点快。这是否回答了您的问题?
SELECT 'Person' as type, t.id, t.name, c.workspace_id FROM union_person t
LEFT JOIN union_change c on t.id = c.record_id and 'Person' = c.table_name
UNION
SELECT 'Pet' as type, t.id, t.name, c.workspace_id FROM union_pet t
LEFT JOIN union_change c on t.id = c.record_id and 'Pet' = c.table_name;