(教义ORM)如何通过多对一关系对SELECT进行排序



我有一个包含类型和类别的数据库(以及其他不相关的东西)。类型类别具有多对一关系。我想要的是选择所有类型行,首先按类别名称排序,然后按类型权重排序,最后按类型名称排序(全部升序)。关键的部分是我希望具有相同类别的所有类型在结果中分组在一起。作为 SQL 新手,我认为一个简单的连接语句后跟适当的语句顺序就足够了。我错了。我得到的结果对我来说毫无意义。

实际结果(类型名称 - 类别名称):

  1. 飞机着陆支柱 -飞机
  2. Aicraft 转子叶片 -飞机
  3. 飞机机翼 -飞机
  4. 自行车车架 -骑行循环
  5. 船头 -船只
  6. 船货甲板 -船只
  7. 巨石底部 -岩石
  8. 博尔德顶部 -岩石
  9. 弓形元素 -其他
  10. 砖 1x1 带果汁纸箱印刷 -砖印刷
  11. 砖 1x1 w/牛奶纸盒印刷 -砖印刷
  12. 洗车刷架 -其他
  13. [等]

预期结果(类型名称 - 类别名称):

  1. 飞机着陆支柱 -飞机
  2. Aicraft 转子叶片 -飞机
  3. 飞机机翼 -飞机
  4. 砖 1x1 带果汁纸箱印刷 -砖印刷
  5. 砖 1x1 w/牛奶纸盒印刷 -砖印刷
  6. 弓形元素 -其他
  7. 洗车刷架 -其他
  8. 自行车车架 -骑行循环
  9. 巨石底部 -岩石
  10. 博尔德顶部 -岩石
  11. 船头 -船只
  12. 船货甲板 -船只
  13. [等]

有超过 2,000 个类型行,因此上面的列表显然非常截断。没有错误。对结果进行分页可能也很重要(这一直很完美)。

我正在使用Doctrine 2.5.x和我自己的内容管理系统。在我使用QueryBuilder类型实体的存储库中,按如下方式构造查询(最大结果是全局设置,第一个结果是根据当前页码在存储库外部计算的):

$qb = $this->createQueryBuilder('t');
$qb->select('t, c'); // omitting this does not change the result
$qb->join('t.category', 'c');
$qb->addOrderBy('c.name', 'ASC'); // this does not work as expected
$qb->addOrderBy('t.weight', 'ASC');
$qb->addOrderBy('t.name', 'ASC');
$qb->setMaxResults(20);
$qb->setFirstResult(0);
return $qb->getQuery()->getResult();

生成的 SQL 语句如下所示:

SELECT b0_.ID AS ID_0, b0_.weight AS weight_1, b0_.name AS name_2, b0_.number AS number_3, b0_.name_alt AS name_alt_4, b0_.note AS note_5, b1_.ID AS ID_12, b1_.slug AS slug_13, b1_.name AS name_14, b1_.`desc` AS desc_15, b0_.cat_id AS cat_id_16 FROM types b0_ INNER JOIN categories b1_ ON b0_.cat_id = b1_.ID ORDER BY b1_.name ASC, b0_.weight ASC, b0_.name ASC LIMIT 20 OFFSET 0

类型实体的设置如下(省略了不相关的字段):

/**
* @Entity(repositoryClass="NevermindRepositoryTypeRepository")
* @Table(name="types", options={"collate"="utf8mb4_unicode_ci", "charset"="utf8mb4"})
*/
class Type {
/**
* @Id
* @Column(type="integer", name="ID")
* @GeneratedValue
*/
protected $id;
/**
* @ManyToOne(targetEntity="Category", inversedBy="types", fetch="EAGER")
* @JoinColumn(name="cat_id", referencedColumnName="ID")
*/
protected $category;
/**
* @Column(type="integer")
*/
protected $weight = 0;
/**
* @Column(type="string", unique=true)
*/
protected $name = '';
/**
* @Column(type="string", unique=true, length=12)
*/
protected $number = '';
/**
* @Column(type="string", nullable=true)
*/
protected $name_alt;
/**
* @Column(type="text", nullable=true)
*/
protected $note;
}

类别实体的设置如下:

/**
* @Entity(repositoryClass="NevermindRepositoryDefaultRepository")
* @Table(name="categories", options={"collate"="utf8mb4_unicode_ci", "charset"="utf8mb4"})
*/
class Category {
/**
* @Id
* @Column(type="integer", name="ID")
* @GeneratedValue
*/
protected $id;
/**
* @Column(type="string", unique=true)
*/
protected $slug = '';
/**
* @Column(type="string", nullable=true)
*/
protected $name;
/**
* @Column(type="text", name="`desc`", nullable=true)
*/
protected $desc;
/**
* @OneToMany(targetEntity="Type", mappedBy="category", fetch="EXTRA_LAZY", cascade={"persist", "remove"})
* @OrderBy({"weight"="ASC", "name"="ASC"})
*/
protected $types;
}

TypeRepository扩展了DefaultRepository,扩展了教义的EntityRepository

结果的奇怪排序是由于类别name列有时null(显示时,名称会回退到slug列的转换内容,这是我完全忘记的更改)。因此,只需将第一个 order-by 语句更改为c.slug即可解决问题。哎呀!

所以请记住,按可以为 null 的列排序会导致奇怪的结果!

你试过吗

$qb->select('t, c');
...
$qb->orderBy('c.name', 'ASC'); // orderBy not addOrderBy for the first clause
$qb->addOrderBy('t.weight', 'ASC');
$qb->addOrderBy('t.name', 'ASC');
...

相关内容

  • 没有找到相关文章

最新更新