【问题标题】:Zend DB Join 2 rows from same tableZend DB 连接来自同一个表的 2 行
【发布时间】:2011-09-20 21:09:05
【问题描述】:

我有下表。

---------------------------------------------
check_id | action_id | user_id |         dt |
---------------------------------------------
       1 |         1 |       6 | 2011-09-17 |
       2 |         1 |       6 | 2011-09-18 |
       3 |         3 |       6 | 2011-09-19 |
       4 |         3 |       6 | 2011-09-20 |
---------------------------------------------

我想查询这张表,得到如下结果。

-----------------------------------------------
action_id | user_id |   dt_start |     dt_end |
-----------------------------------------------
       1 |        6 | 2011-09-17 | 2011-09-18 |
       3 |        6 | 2011-09-19 | 2011-09-20 |
-----------------------------------------------

所以我使用以下查询。

$checks->select()
->from(array('c1' => 'checks'), array('dt as dt_start')
->joinLeft(array('c2' => 'checks'), 'c1.action_id = c2.action_id', array('dt as dt_end')
->where('c1.user_id = ?', $userId)
->group('c1.action_id')

但这给了我以下结果。

-----------------------------------------------
action_id | user_id |   dt_start |     dt_end |
-----------------------------------------------
       1 |        1 | 2011-09-17 | 2011-09-17 |
       1 |        3 | 2011-09-19 | 2011-09-19 |
-----------------------------------------------

谁能告诉我我做错了什么?

【问题讨论】:

  • 我并不清楚您试图通过 Zend_Db_Select 创建什么 SQL。您可以将 SQL 添加到问题中吗?另外,您可以使用 Zend_Db_Select::toString 方法打印查询时将执行的 SQL,这可能有助于您调试。

标签: zend-framework join zend-db zend-db-table


【解决方案1】:

试试这个查询,没有 group by

SELECT *
FROM checks c1 LEFT OUTER JOIN checks c2 ON c1.action_id = c2.action_id 
WHERE c1.user_d = 6

你会看到你得到匹配的地方 c1.dt c2.dt 和 c1.dt = c2.dt 的地方得到匹配。 也就是说,自联接包括 c1 和 c2 指向同一行的结果。

然后您使用 GROUP BY 将多行合并为一个,但 MySQL 从组中选择任意行。 (这是一个模棱两可的查询,如果你 SET SQL_MODE='ONLY_FULL_GROUP_BY' 你会得到一个错误。)

因此,您的自联接和 GROUP BY 返回实际上是同一行的 c1 和 c2。

要解决这个问题,您应该添加一个条件,即 c1.dt

$checks->select()
->from(array('c1' => 'checks'), array('dt as dt_start')
->joinLeft(array('c2' => 'checks'), 
           'c1.action_id = c2.action_id AND c1.dt < c2.dt', 
           array('dt as dt_end')
->where('c1.user_id = ?', $userId)

在这种情况下,您可能根本不需要 GROUP BY,假设每个操作没有多个开始和结束。

顺便说一句,这种类型的复杂性是通常建议将事件开始/结束数据存储在单行中的原因之一,开始在一列中,结束在第二列中。

【讨论】:

  • 使用 GROUP BY action_id 可以得到我需要的结果。我也可以使用 joinRight ,但这也给了我只有一行的结果。当两行共享相同的 action_id 时,我需要结果。也许将开始日期和结束日期存储在一行中是更好的解决方案。我正在构建一个入住/退房系统。
  • 右连接不会返回 action_id 尚未与另一行共享的行。我也需要那些。所以一个 LEFT JOIN 结合一个 GROUP BY 就可以了。
  • 没关系,但是你得到我提到的关于测试 fot c1.dt
猜你喜欢
  • 1970-01-01
  • 2013-07-04
  • 2021-11-02
  • 2013-11-11
  • 1970-01-01
  • 2022-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多