在 Django 中编写原始 sql CTE

问题描述 投票:0回答:1

我有一个团队层次结构模型

class Hrc(models.Model):
    id = models.UUIDField(default=uuid.uuid4, primary_key=True, unique=True, editable=False)
    emp = models.ForeignKey('Employee', on_delete=models.CASCADE, related_name='emp')
    mang = models.ForeignKey('Employee', on_delete=models.CASCADE, related_name='mang')
    created_on = models.DateTimeField(auto_now_add=True)


    class Meta:
        ordering = ['created_on']

由于我想获取特定员工下的层次结构,因此我想使用 CTE。我想在我拥有的 Django 信号之一中编写 CTE。以下是我收到的信号

@receiver(post_save, sender=Employee)
def employeeUpdated(sender, instance, created, **kwargs):
    if not created:
        //I want to get the hierarchy under an employee (instance in this case). So the 
        // CTE should be written here

我要写的CTE是

with hierarchy as 
(
  select emp, mang, 1 as lvl
  from hrc 
  where emp = instance
  
  union all
  
  select child.emp, parent.emp, lvl+1
  from hierarchy as parent
  join hrc as child
      on child.mang = parent.emp
), lvls as (
    select lvl, emp
    from hierarchy
    group by lvl, emp
)
select lvl, STRING_AGG(emp, '') within group (order by emp)
from lvls
group by lvl;

我怎样才能在信号中写入这个cte并得到想要的结果。

sql django common-table-expression
1个回答
0
投票

应该可以了。它将利用 Django 的“原始 SQL 查询”功能。 使用 %s 根据您的需要更改传递给 SQL 语句的参数。

from django.db import connection


@receiver(post_save, sender=Employee)
def employeeUpdated(sender, instance, created, **kwargs):
    if not created:
        with connection.cursor() as cursor:
            cursor.execute("""
                WITH hierarchy
                AS (
                    SELECT emp
                        ,mang
                        ,1 AS lvl
                    FROM hrc
                    WHERE emp = %s
                    UNION ALL
                    SELECT child.emp
                        ,parent.emp
                        ,lvl + 1
                    FROM hierarchy AS parent
                    INNER JOIN hrc AS child ON child.mang = parent.emp
                    )
                    ,lvls
                AS (
                    SELECT lvl
                        ,emp
                    FROM hierarchy
                    GROUP BY lvl
                        ,emp
                    )
                SELECT lvl
                    ,STRING_AGG(emp, '') within
                GROUP (
                        ORDER BY emp
                        )
                FROM lvls
                GROUP BY lvl;""",
                [instance.pk]
            )
            row = cursor.fetchall()
        # do whatever you need to do with the result

© www.soinside.com 2019 - 2024. All rights reserved.