MySQL SELECT SUM(列)和SELECT *基数违规:1241操作数应包含1列

时间:2013-06-23 14:25:58

标签: php mysql select

尝试编写语句,在单个语句中选择all(*)并将同一数据库和同一个表中的一列相加,具体取决于条件。

写了这样的陈述(基于这个Multiple select statements in Single query

SELECT ( SELECT SUM(Amount) FROM 2_1_journal), ( SELECT * FROM 2_1_journal WHERE TransactionPartnerName = ? )

我了解SELECT SUM(Amount) FROM 2_1_journal将对Amount列中的所有值求和(不基于编码)。

但首先要了解什么是正确的陈述

使用上述语句获取错误SQLSTATE[21000]: Cardinality violation: 1241 Operand should contain 1 column(s)

无法理解错误消息。根据此处的建议MySQL - Operand should contain 1 column(s)了解子查询SELECT * FROM 2_1_journal WHERE TransactionPartnerName = ?必须只选择一列?

尝试将语句更改为此SELECT ( SELECT * FROM 2_1_journal WHERE TransactionPartnerName = ? ), ( SELECT SUM(Amount) FROM 2_1_journal),但得到相同的错误......

什么是正确的陈述?

1 个答案:

答案 0 :(得分:2)

SELECT *, (SELECT SUM(Amount) FROM 2_1_journal)
  FROM 2_1_journal
 WHERE TransactionPartnerName = ?

这将从整个表中选择总结Amount并“追加”TransactionPartnerName是您在客户端代码中绑定的参数的所有行。

如果要将总和限制为与您选择的行相同的条件,请将其包括在内:

SELECT *, (SELECT SUM(Amount) FROM 2_1_journal WHERE TransactionPartnerName = ?)
  FROM 2_1_journal
 WHERE TransactionPartnerName = ?

完全不同的是:像2_1_journal这样的表名是数据库设计损坏的强有力指标。如果您可以重做它,您应该研究如何正确地规范化数据库。它很可能会多次收回。

关于规范化(稍后补充):

由于当前设计使用表名中的键(例如2中的12_1_journal),我将很快说明我认为您可以大大改进该设计。让我们说表2_1_journal有以下数据(我只是在这里猜测,因为这些表尚未在任何地方描述):

title | posted     | content
------+------------+-----------------
Yes!  | 2013-01-01 | This is just a test
2nd   | 2013-01-02 | Another test

此内容属于公司2中的用户1。但是嘿!如果您查看行,则无法找到此数据属于公司2中的用户1的事实。

问题是此设计违反了数据库设计的最基本原则之一:不要在对象(此处为:表)名称中使用键。如果你必须在添加新内容时创建新表,那么明确指出某些内容是非常错误的。在这种情况下,添加新用户或新公司需要添加新表。

这个问题很容易解决。创建名为journal一个表。接下来,使用相同的列,但添加另外两列:

company | user | title | posted     | content
--------+------+-------+------------+-----------------
      1 |    2 | Yes!  | 2013-01-01 | This is just a test
      1 |    2 | 2nd   | 2013-01-02 | Another test

这样做意味着:

  • 除非应用程序发生变化,否则永远不会添加或修改表。
  • 跨公司或用户进行联接(现在可以通过一个相当简单的select语句来实现其他任何曾经属于表命名方案的联接。)
  • 实施完整性很容易 - 如果您升级应用程序并想要更改表格,则不必为每个公司和用户重复更改。更重要的是,这降低了使应用程序与数据库中的表不同步的风险(例如将字段comments添加到所有x_y_journal表,但忘记5313_4324_journal导致用户5313登录时应用程序仅打开 。这是您不想处理的问题。

我不是写这个,因为这是个人品味的问题。数据库只是为处理如上所述的表格而设计的。将对象键作为表名的一部分使用的设计存在许多与之相关的其他难以处理的问题。