【问题标题】:MySQL SELECT SUM(Column) and SELECT * Cardinality violation: 1241 Operand should contain 1 column(s)MySQL SELECT SUM(Column) 和 SELECT * 基数违规:1241 操作数应包含 1 列
【发布时间】:2013-06-20 03:31:54
【问题描述】:

尝试编写语句 where in single statement select all (*) and sum one column from the same database and the same table, 具体取决于条件。

写了这样的声明(基于这个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),但得到相同的错误...

什么是正确的陈述?

【问题讨论】:

    标签: php mysql select


    【解决方案1】:
    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_1_journal 中的21),我将快速说明我认为您可以如何极大地改进该设计。假设表 2_1_journal 具有以下数据(我只是在这里猜测,因为尚未在任何地方描述表):

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

    这东西属于公司1中的用户2。但是,嘿!如果您查看这些行,则找不到该数据属于公司1 中的用户2 的事实。

    问题在于这种设计违反了数据库设计的最基本原则之一:不要在对象(这里:表)名称中使用键。一个非常错误的明确迹象是,如果添加了新表,则必须创建新表。在这种情况下,添加新用户或新公司需要添加新表。

    这个问题很容易解决。创建 一个 名为 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 登录时。这是您不想处理的问题。

    我不会写这个,因为这是个人品味的问题。数据库只是为了处理我上面描述的布局的表而设计的。将对象键用作表名的一部分的设计存在许多与之相关的其他问题,这些问题非常难以处理。

    【讨论】:

    • 关于表名与_相关的问题?这样的表名是因为: i) 表:users 并且每个用户都有自己的编号(例如,编号 2)。 ii) 那么表号2_ 仅与特定用户相关。此表中包含公司,与特定用户相关,公司编号,如 1、2、3、4; iii) 对于每家公司,都有几个表,例如日记帐、员工、仓库。所以 2_1_journal 表示用户 2 号、公司 1 号的日志。我考虑表名,这是我选择的解决方案....
    • 您是否考虑在likejournal 等表中添加一个名为Company 的列?您正在做的事情非常不合常规,并且可能会在未来一段时间内引起问题。
    • 您可以在此处查看有关规范化的教程:youtube.com/watch?v=ygfikznRjpwholowczak.com/database-normalization
    • 您的意思是使用2CompanyJournal 而不是2_1_journal?感谢您提供信息,我会考虑其他解决方案。当我考虑命名时,想要让所有表名都是唯一的,目前我已经忘记了(不确定),但假设2 或没有_ 的数字或类似的东西是不允许的。如果我使用UsernameCompanynameJournal,那么表名将不是唯一的,因为不同的用户可以使用相同的用户名(比如这里freshbooks.com
    • 从长远来看,我上面建议的更改将为您节省大量时间。相信我:)
    猜你喜欢
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 2013-11-20
    • 2013-03-27
    • 1970-01-01
    相关资源
    最近更新 更多