【问题标题】:Join and add data in SQL and sqlalchemy在 SQL 和 sqlalchemy 中加入和添加数据
【发布时间】:2017-12-14 05:01:39
【问题描述】:

我是 MySQL 和 sqlalchemy 的新手。

所以 Subquery_A 给了我大约 1,000 个结果:

 [(customer_id, days_a_customer)...]

Subquery_B 以表格形式提供了大约 30,000 个结果:

 [(customer_id, transaction_id)...]

Subquery_A 表示“days_a_customer”值大于 30 的客户 ID。Subquery_B 表示所有客户的交易事件。

如何合并这两个子查询,以便获得 subquery_B 中所有在 subquery_A 中具有“customer_id”值的行以及来自 subquery_A 的“days_a_customer”,即:

Subquery_C = [(customer_id, transaction_id, days_a_customer)...]

其中 Subquery_C 表示客户执行的所有交易事件,且已存在超过 30 天。

首选 sqlalchemy 特定的帮助,但也非常感谢原始 SQL。

【问题讨论】:

    标签: mysql sql join sqlalchemy


    【解决方案1】:

    根据你的问题,我猜你想要:

    • 成为客户超过 30 天并拥有 交易。

    所有客户都在一个表中,交易在一个单独的表中。为了满足这个问题,我们可以使用客户和交易表之间的内连接(只返回两个表中的那些记录)和过滤方法来过滤作为客户的天数。该方法如下面的示例所示。

    from sqlalchemy import Column, Integer, String, DateTime
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import create_engine, ForeignKey
    from sqlalchemy.orm import sessionmaker, relationship
    from random import randint
    
    Base = declarative_base()
    
    
    ## Define sample models
    
    
    class Customer(Base):
        __tablename__ = 'customer'
        customer_id = Column('id', Integer, primary_key=True)
        nr_days_customer = Column('nr_days_customer', Integer)
        name = Column('name', String(250))
        transaction = relationship('Transaction', back_populates='customer')
    
        def __init__(self, nr_days_customer, name):
            self.nr_days_customer = nr_days_customer
            self.name = name
    
        def __repr__(self):
            return '[{customer_id}] - {name} - {nr_days_customer} days'.format(customer_id=self.customer_id,
                                                                               name=self.name,
                                                                               nr_days_customer=self.nr_days_customer)
    
    
    class Transaction(Base):
        __tablename__ = 'transaction'
        transaction_id = Column('id', Integer, primary_key=True)
        customer_id = Column('customer_id', Integer, ForeignKey('customer.id'))
        name = Column(String(250))
        customer = relationship('Customer', back_populates='transaction')
    
        def __init__(self, customer_id, name):
            self.customer_id = customer_id
            self.name = name
    
        def __repr__(self):
            return '[{transaction_id}] {name} - customer: {customer_id}'.format(transaction_id=self.transaction_id,
                                                                                name=self.name,
                                                                                customer_id=self.customer_id)
    
    
    engine = create_engine('sqlite:///')
    session = sessionmaker()
    session.configure(bind=engine)
    ex_ses = session()
    Base.metadata.create_all(engine)
    
    ## Create sample data
    
    # http://listofrandomnames.com/ for something else then A,B,...
    names = ['Virgil', 'Ina', 'Oleta', 'Suzette', 'Usha', 'Ilda', 'Lorean', 'Cinthia', 'Sheba', 'Waneta', 'Donnette',
             'Minerva', 'Owen', 'Georgia', 'Gertrudis', 'Sherika', 'Terry', 'Deja', 'Regena', 'Carolin']
    
    # Create customers > 30 days with transaction
    for customer_nr in range(5):
        ex_ses.add(Customer(name=names[customer_nr].format(customer_nr),
                            nr_days_customer=randint(30, 120)))
    
    # Create customers < 30 days with transaction
    for customer_nr in range(5):
        ex_ses.add(Customer(name=names[customer_nr + 5].format(customer_nr),
                            nr_days_customer=randint(0, 29)))
    
    # Create customers > 30 days without transaction
    for customer_nr in range(5):
        ex_ses.add(Customer(name=names[customer_nr + 10].format(customer_nr),
                            nr_days_customer=randint(30, 120)))
    
    # Create customers < 30 days without transaction
    for customer_nr in range(5):
        ex_ses.add(Customer(name=names[customer_nr + 15].format(customer_nr),
                            nr_days_customer=randint(0, 29)))
    
    # Create transactions
    for transaction_nr in range(10):
        ex_ses.add(Transaction(name='Transaction {}'.format(transaction_nr), customer_id=transaction_nr + 1))
    
    ex_ses.commit()
    
    # Queries
    print('customers:')
    for customer in ex_ses.query(Customer).all():
        print('* ', customer)
    
    '''
    customers:
    *  [1] - Virgil - 113 days
    *  [2] - Ina - 112 days
    *  [3] - Oleta - 44 days
    *  [4] - Suzette - 61 days
    *  [5] - Usha - 82 days
    *  [6] - Ilda - 10 days
    *  [7] - Lorean - 14 days
    *  [8] - Cinthia - 24 days
    *  [9] - Sheba - 25 days
    *  [10] - Waneta - 11 days
    *  [11] - Donnette - 38 days
    *  [12] - Minerva - 110 days
    *  [13] - Owen - 98 days
    *  [14] - Georgia - 68 days
    *  [15] - Gertrudis - 36 days
    *  [16] - Sherika - 18 days
    *  [17] - Terry - 6 days
    *  [18] - Deja - 7 days
    *  [19] - Regena - 21 days
    *  [20] - Carolin - 14 days
    '''
    
    print('Transactions:')
    for transaction in ex_ses.query(Transaction).all():
        print('* ', transaction)
    
    '''
    Transactions:
    *  [1] Transaction 0 - customer: 1
    *  [2] Transaction 1 - customer: 2
    *  [3] Transaction 2 - customer: 3
    *  [4] Transaction 3 - customer: 4
    *  [5] Transaction 4 - customer: 5
    *  [6] Transaction 5 - customer: 6
    *  [7] Transaction 6 - customer: 7
    *  [8] Transaction 7 - customer: 8
    *  [9] Transaction 8 - customer: 9
    *  [10] Transaction 9 - customer: 10
    '''
    
    
    '''
    -- using inner join only records in both tables are being returned
    -- https://www.w3schools.com/sql/sql_join.asp
    -- condition on more then 30 days
    -- untested SQL:
    SELECT customer.customer_id, transaction.transaction_id, customer.days_a_customer from customer
    INNER JOIN transaction ON customer.customer_id = transaction.customer_id
    WHERE customer.days_a_customer > 30 AND customer.customer_id.
    '''
    
    print('Customer - transactions:')
    for cust_trans in ex_ses.query(Customer.name, Customer.nr_days_customer,Transaction.transaction_id).join(Transaction).filter(
            Customer.nr_days_customer > 30).all():
        print('* Customer {customer_name} - {nr_days_customer} --> transaction {transaction_id}'.format(
            customer_name = cust_trans[0],nr_days_customer=cust_trans[1],transaction_id=cust_trans[2]))
    
    '''
    Customer - transactions:
    * Customer Virgil - 113 --> transaction 1
    * Customer Ina - 112 --> transaction 2
    * Customer Oleta - 44 --> transaction 3
    * Customer Suzette - 61 --> transaction 4
    * Customer Usha - 82 --> transaction 5
    '''
    

    正如您在注释文本中看到的那样,此查询仅返回 5 个客户超过 30 天且在交易表中的客户。

    在 cmets 中提供了指向更多资源的 fez 链接。除此之外,我想强调以下其他资源:

    我在上面的例子中没有使用 mysql。我相信提供的示例可以轻松应用于 mysql 设置。

    如果有其他问题,请发表评论。

    【讨论】:

      猜你喜欢
      • 2011-07-24
      • 2023-04-09
      • 1970-01-01
      • 2020-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多