MySQL:如何查询复合主键?具体来说,一个不在查询中的?
我有一个MySQL:如何查询复合主键?具体来说,一个不在查询中的?,mysql,cakephp,composite-primary-key,notin,phinx,Mysql,Cakephp,Composite Primary Key,Notin,Phinx,我有一个comment表和一个comment\u edit表,以及olddb\u edit。简化后,相关表格如下所示: CREATE TABLE `olddb_edit` ( edit_id INT NOT NULL, edit_time INT NOT NULL, edit_text TEXT NOT NULL, PRIMARY KEY (edit_id, edit_time) ) ENGINE=InnoDB; $skippable = array(
comment
表和一个comment\u edit
表,以及olddb\u edit
。简化后,相关表格如下所示:
CREATE TABLE `olddb_edit` (
edit_id INT NOT NULL,
edit_time INT NOT NULL,
edit_text TEXT NOT NULL,
PRIMARY KEY (edit_id, edit_time)
) ENGINE=InnoDB;
$skippable = array(
array('id' => 707969, 'time' => 1434462225),
array('id' => 707969, 'time' => 1434462463),
array('id' => 707969, 'time' => 1434462551),
);
现在我想将内容从另一个DB迁移到编辑表中,但跳过一些表行,如测试注释。我使用CakePHP来实现这一点(实际上是Phinx)
通常,这就足够了:
$skippable = array(
12345, 23456, 34567, 45678,
);
$rows = $this->getQueryBuilder()
->select('*')
->from('olddb_comment')
->where(array(
'comment_id NOT IN' => $skippable,
))
->execute()
->fetchAll('assoc')
;
但是一个简单的notin
子句显然不适用于复合主键
我在想,$skippable
数组应该如下所示:
CREATE TABLE `olddb_edit` (
edit_id INT NOT NULL,
edit_time INT NOT NULL,
edit_text TEXT NOT NULL,
PRIMARY KEY (edit_id, edit_time)
) ENGINE=InnoDB;
$skippable = array(
array('id' => 707969, 'time' => 1434462225),
array('id' => 707969, 'time' => 1434462463),
array('id' => 707969, 'time' => 1434462551),
);
然后我将通过for循环或其他方式运行where子句。但老实说,我甚至不知道如何在香草MySQL中做到这一点
可能已经发布了一个解决方案,但我找不到任何解决方案(除了特定于其他应用程序的解决方案)。我想这个算法不是我的朋友。没关系,我在制定问题的时候自己弄明白了。不管怎样,我会把答案贴出来,给其他有类似问题的人
首先,香草MySQL。如果您不在(imo)中分解
,这与您想象的一样直观:
使用CakePHP/Phinx查询生成器,可以使用匿名函数、for循环和not或构造:
$qb = $this->getQueryBuilder()
->select('*')
->from('olddb_edit')
->where(array(
'edit_some_other_optional_condition = 1',
))
// also skip skippables.
->where(function($exp) use ($skippable) {
$ORed = array();
foreach ($skippable as $edit) {
array_push($ORed, array(
'edit_id' => $edit['id'],
'edit_time' => $edit['time'],
));
}
return $exp->not($exp->or_($ORed));
})
;
更新:根据@ndm的评论,我使用TupleComparison提供了一个令人满意的解决方案(@ndm,如果您愿意,请随时发布您的答案。我将删除/编辑我的答案,然后选择您的答案。您应该获得此荣誉)
您的查询的计算结果如下:;你确定这就是你想要的吗
select edit_id
, edit_time
, edit_text
from olddb_edit
where
(
(
(edit_id <> 707969)
or (edit_time <> 1434461454)
)
and (
(edit_id <> 707969)
or (edit_time <> 1434461503)
)
and (
(edit_id <> 707969)
or (edit_time <> 1434461925)
)
);
选择编辑\u id
,编辑时间
,编辑文本
从olddb_编辑
哪里
(
(
(编辑编号707969)
或(编辑时间1434461454)
)
及(
(编辑编号707969)
或(编辑时间1434461503)
)
及(
(编辑编号707969)
或(编辑时间1434461925)
)
);
在SQL中,元组也可以工作,而不是展开不在
中的。比如:(edit\u id,edit\u time)notin((707969143441454),(707969143441503),…)
@stickybit我发现或不非常混乱,所以我可能弄错了,但我认为你的查询在逻辑上是不同的(很可能是OP想要的)。@草莓:嗯,我不知道。。。首先要注意的是,我在这个答案中引用了SQL,不是问题中的任何东西,也不是任何PHP的东西,如果不清楚的话。然后我的推理是:NOT
后面括号中的所有内容都可以用元组表示为in
。使用元组覆盖和
s,然后它是一组具有相同左操作数的或
s,可以在
中表示为。所以我们得到了而不是(…IN…
)。这可以简化为不在…
中。当然,我可能在某个地方错了。也许你可以构造一个反例?我不知道不在
支持的元组中,或者这是一件事(在插入
语句之外)。我在dev.mysql.com上找不到(现在仍然找不到)任何关于这方面的官方文档……我会调查一下,看看这其中是否有CakePHP的东西。有一个用于元组比较的表达式:请问一个特定的问题:你到底在哪里。对于代码问题,给出一个give a--cut&paste&runnable代码,包括作为代码输入的最小代表性示例;期望和实际输出(包括逐字记录错误消息);标签和版本;清晰的说明和解释。对于SQL、DBMS和DDL(包括约束和索引)以及作为表格式的代码输入。查询时不需要PS键。连接基于条件,而不是关键点。在for子查询中,接受的是行,而不是键。是否为多列是DBMS特有的。“典型存在”是一个更好的选择。这是一个奇怪的看待它的方式,但本质上是:是的。这就是我想要的。同时是每个可跳过行的求反的表行。毕竟,这就是不在
中的是什么。