【问题标题】:automatically insert only one row in table after calculating the sum of column计算列总和后自动在表中只插入一行
【发布时间】:2020-08-07 14:46:18
【问题描述】:

我的数据库中有 3 个表

 CREATE TABLE IF NOT EXISTS  depances (
            id SERIAL PRIMARY KEY UNIQUE NOT NULL, 
            type VARCHAR NOT NULL,
            nom VARCHAR,
            montant DECIMAL(100,2) NOT NULL,
            date DATE,
            temp TIME)
CREATE TABLE IF NOT EXISTS transactions (
            id SERIAL PRIMARY KEY  UNIQUE NOT NULL,
            montant DECIMAL(100,2), 
            medecin VARCHAR,
            patient VARCHAR, 
            acte VARCHAR,
            date_d DATE, 
            time_d TIME,
            users_id INTEGER)
 CREATE TABLE IF NOT EXISTS  total_jr (
            id SERIAL PRIMARY KEY UNIQUE NOT NULL, 
            total_revenu DECIMAL(100,2),
            total_depance DECIMAL(100,2),
            total_différence DECIMAL(100,2),
            date DATE)

我的想法是使用 GUI 界面在 table depances 和 transaction 中插入 defrent 值。 然后在 total_depance.total_jr 中添加 montant.depances 的总和 以及 total_revenu.total_jr 中 montant.transactions 的总和,其中所有行都具有相同的时间 这是使用此代码的简单部分

self.cur.execute( '''SELECT SUM(montant) AS totalsum FROM depances WHERE date = %s''',(date,))
        result = self.cur.fetchall()
        for i in result:
            o = i[0]
        
        self.cur_t = self.connection.cursor()

        self.cur_t.execute( '''INSERT INTO total_jr(total_depance) 
            VALUES (%s)'''
        , (o,))
        self.connection.commit()

        self.cur.execute( '''UPDATE total_jr SET total_depance = %s WHERE date = %s''',(o, date))
        self.connection.commit()

但是每次它都会在total_jr的表中添加一个新行

如何将 SUM(montant) 的值添加到表中,其中每次仅将 sum 的值放在一行而不是每次添加新行时日期都相同 结果应该是这样的

id|total_revenu|total_depance|total_différence|date
--+------------+-------------+----------------+----
1  sum(montant1) value         value            08/07/2020
2  sum(montant2) value         value            08/09/2020
3  sum(montant3) value         value            08/10/2020

但它只给我这个结果

id|total_revenu|total_depance|total_différence|date
--+------------+-------------+----------------+----
1   1           value         value            08/07/2020
2   2           value         value            08/07/2020
3   3           value         value            08/7/2020

如果有任何想法或任何打击将是 hulpefull

【问题讨论】:

  • 。 . select 不会向表中添加行。
  • 是的,我只是为了展示我如何计算 SUM self.cur.execute( '''SELECT SUM(montant) AS totalsum FROM depances WHERE date = %s''',(date,)) result = self.cur.fetchall() for i in result: o = i[0] self.cur_t = self.connection.cursor() self.cur_t.execute( '''INSERT INTO total_jr(total_depance) VALUES (%s)''' , (o,)) self.connection.commit() 这是我计算 SUM 的完整代码,它可以正常工作
  • 我的问题是如何自动将一行添加到只有一个日期值的表中(这将不是具有相同日期的 2 行)

标签: python sql database postgresql


【解决方案1】:

你没有提到你使用的是哪个 DBMS 或 SQL 模块,所以我猜是 MySQL。

在您的过程中,首先运行更新并检查更改了多少行。如果零行更改,则为该日期插入一个新行。

self.cur.execute( '''SELECT SUM(montant) AS totalsum FROM depances WHERE date = %s''',(date,))
result = self.cur.fetchall()
for i in result:
    o = i[0]

self.cur.execute( '''UPDATE total_jr SET total_depance = %s WHERE date = %s''',(o, date))

rowcnt = self.cur.rowcount  # number of rows updated - psycopg2
self.connection.commit()

if rowcnt == 0:  # no rows updated, need to insert new row
    self.cur_t = self.connection.cursor()

    self.cur_t.execute( '''INSERT INTO total_jr(total_depance, date) 
        VALUES (%s, %s)'''
    , (o, date))
    self.connection.commit()

【讨论】:

  • 您好,感谢您的回复,我正在使用 postgresql,但我尝试使用此代码时,它向我显示了此错误`AttributeError: 'psycopg2.extensions.connection' object has no attribute 'affected_row'` 在搜索后我必须使用UPSERT(我还不知道如何使用它,但是如果它不存在并且如果它exicte它只更新total_depance,它就像我插入一个新行一样
  • 我更新了 psycopg2 的代码。使用 UPSERT 可能会更好,因为它需要更少的数据库调用。
  • 你好,我很抱歉,但它确实有效,因为首先,该行没有执行,所以当它运行 isert 命令时,日期将为空,如果我删除该行并尝试运行它什么都不做的功能谢谢你的帮助我会尝试再次学习如何使用UPSERT命令thanx来使用它
【解决方案2】:

我为将来需要它的任何人找到解决方案首先我们需要更新表格

        create_table_total_jr = ''' CREATE TABLE IF NOT EXISTS  total_jr (
            id SERIAL PRIMARY KEY UNIQUE NOT NULL, 
            total_revenu DECIMAL(100,2),
            total_depance DECIMAL(100,2),
            total_différence DECIMAL(100,2),
            date DATE UNIQUE)''' #add unique to the date 

然后我们使用 UPSERT 和 ON CONFLICT

 self.cur_t.execute( ''' INSERT INTO total_jr(date) VALUES (%s)
        ON CONFLICT (date) DO NOTHING''', (date,))
        self.connection.commit()

当有一个相同日期的插入值时,使用此代码将不会执行任何操作 之后我们更新 SUM 的值

 self.cur.execute( '''UPDATE total_jr SET total_depance = %s WHERE date = %s''',(o, date))
        self.connection.commit()

特别感谢 Mike67 的帮助

【讨论】:

    【解决方案3】:

    您不需要为此进行 2 次数据库调用。正如@Mike67 建议的那样,UPSERT 功能就是您想要的。但是,您需要同时发送 date 和 total_depance。在 SQL 中变成:

    insert into total_jr(date,total_depance) 
           values (date_value, total_value
            on conflict (date) 
            do update  
               set total_depance = excluded.total_depance;  
           
    

    或者取决于输入的 total_depance 只是交易值,而在表上 total_depance 是一个累积:

    insert into total_jr(date,total_depance) 
           values (date_value, total_value
            on conflict (date) 
            do update  
               set total_depance = total_depance + excluded.total_depance;
    

    我相信你的代码会变成这样(假设第一个插入是正确的)

    self.cur_t.execute( ''' INSERT INTO total_jr(date,total_depance) VALUES (%s1,$s2)
            ON CONFLICT (date) DO UPDATE set total_depance = excluded.$s2''',(date,total_depance))
        self.connection.commit()  
    

    但这可能会关闭,您需要验证。

    每日提示:您应该将列名 日期 更改为其他名称。 Date 在 Postgres 和 SQL 标准中都是保留字。它具有基于其上下文的预定义含义。虽然您可以将其用作数据名称,但 Postgres 仍然有权随时更改它,恕不另行通知,这不太可能,但仍然是正确的。如果是这样,那么您的代码(以及使用该表/那些表的大多数代码)将失败,并且追踪原因变得非常困难。基本规则不使用保留字作为数据名称;使用保留字作为数据或数据库对象名称是一个等待咬人的错误。

    【讨论】:

    • 非常感谢@Belayer,它真的帮助我更好地组织我的代码,感谢您的提示
    猜你喜欢
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-23
    • 1970-01-01
    相关资源
    最近更新 更多