【问题标题】:ZF2 Union + PaginationZF2联合+分页
【发布时间】:2013-09-23 13:59:03
【问题描述】:

我正在使用 ZF2 和 SQL Server 2012。我正在尝试使用分页编写联合查询。

ZF2 中似乎还没有完全支持工会。没有union() 方法,但我看到有combine() 方法。它使用联合创建查询,但它将ORDER BY 放在第一个查询上,而不是放在整个联合查询上。因此,当 ZF2 分页器尝试添加限制/偏移部分时,SQL Server 会阻塞,因为它必须在整个查询中使用 ORDER BY

这是我的代码:

public function fetchPage($fkADUser, array $orderBy, $page = 1, $limit = 20) {

    $inboxSelect = $this->inboxTableGateway->getSql()
        ->select()
        ->columns([
            'pkid',
        ])
        ->join(['f' => 'Fax'], 'FaxInbound.fkFax = f.pkid', [
            'PageCount',
            'CreateTime',
        ])
        ->where(['f.fkADUser = ?' => $fkADUser])
        ->where('FaxInbound.DeleteTime IS NOT NULL');

    $sentSelect = $this->sentTableGateway->getSql()
        ->select()
        ->columns([
            'pkid',
        ])
        ->join(['f' => 'Fax'], 'FaxOutbound.fkFax = f.pkid', [
            'PageCount',
            'CreateTime',
        ])
        ->where(['f.fkADUser = ?' => $fkADUser])
        ->where('FaxOutbound.DeleteTime IS NOT NULL');

    $inboxSelect->combine($sentSelect)->order($orderBy);

    return $this->inboxTableGateway->paginate($inboxSelect, $page, $limit, $this->resultSetPrototype);
}

这是生成的查询(来自 SQL Profiler):

(
    SELECT
        [FaxInbound].[pkid] AS [pkid],
        [f].[PageCount] AS [PageCount],
        [f].[CreateTime] AS [CreateTime]
    FROM
        [FaxInbound]
        INNER JOIN [Fax] AS [f]
            ON [FaxInbound].[fkFax] = [f].[pkid]
    WHERE
        f.fkADUser = @P1
        AND FaxInbound.DeleteTime IS NOT NULL
    ORDER BY
        [CreateTime] DESC
) UNION (
    SELECT
        [FaxOutbound].[pkid] AS [pkid],
        [f].[PageCount] AS [PageCount],
        [f].[CreateTime] AS [CreateTime]
    FROM
        [FaxOutbound]
        INNER JOIN [Fax] AS [f]
            ON [FaxOutbound].[fkFax] = [f].[pkid]
    WHERE
        f.fkADUser = @P2
        AND FaxOutbound.DeleteTime IS NOT NULL
)
OFFSET 0 ROWS
FETCH NEXT 20 ROWS ONLY

请注意,ORDER BY 位于第一个查询上,而不是整个联合查询上。所以我得到的错误信息是:

Msg 156, Level 15, State 1, Line 13
Incorrect syntax near the keyword 'ORDER'.
Msg 102, Level 15, State 1, Line 28
Incorrect syntax near 'OFFSET'.
Msg 153, Level 15, State 2, Line 29
Invalid usage of the option NEXT in the FETCH statement.

但如果我将ORDER BY 移到外面,就在OFFSET 之前,查询就可以工作。

所以问题是,有谁知道如何将ORDER BY 放在整个查询而不是第一个?或者,有没有办法让我通过手动编写的查询来使用 ZF2 Paginator?

【问题讨论】:

  • 我不知道这在语法上是否有效,但是像($inboxSelect->combine($sentSelect))->order($orderBy);这样的东西呢
  • @MaxVernon:没关系。 order() 是 Zend\Db\Sql\Select 类的一个方法。在它周围加上括号并不会改变它所调用的类。 combine() 函数返回自身。

标签: php sql-server pagination zend-framework2 union


【解决方案1】:

ZF2 中似乎有一个错误。我把它添加到ZF2 issue tracker

我通过重新排序 Zend\Db\Sql\Select::$specifications 中的条目来解决此问题。

原文:

protected $specifications = array(
    'statementStart' => '%1$s',
    self::SELECT => array(...),
    self::JOINS  => array(...),
    self::WHERE  => 'WHERE %1$s',
    self::GROUP  => array(...),
    self::HAVING => 'HAVING %1$s',
    self::ORDER  => array(...),
    self::LIMIT  => 'LIMIT %1$s',
    self::OFFSET => 'OFFSET %1$s',
    'statementEnd' => '%1$s',
    self::COMBINE => '%1$s ( %2$s )',
);

新:

protected $specifications = array(
    'statementStart' => '%1$s',
    self::SELECT => array(...),
    self::JOINS  => array(...),
    self::WHERE  => 'WHERE %1$s',
    self::GROUP  => array(...),
    self::HAVING => 'HAVING %1$s',
    'statementEnd' => '%1$s',
    self::COMBINE => '%1$s ( %2$s )',
    self::ORDER  => array(...),
    self::LIMIT  => 'LIMIT %1$s',
    self::OFFSET => 'OFFSET %1$s',
);

我刚刚将 ORDER、LIMIT 和 OFFSET 移到了末尾。这为我修复了查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多