I'd like to do a and clause with two lists of multiple or clauses from the same table.
The problem with the following code is, that the query result is empty. If I just select 'indices' or 'brokers', the result is fine.
...
query = query.join(StockGroupTicker, on=(Ticker.id == StockGroupTicker.ticker))
# indices
if "indices" in filter:
where_indices = []
for f in filter["indices"]:
where_indices.append(StockGroupTicker.stock_index == int(f))
if len(where_indices):
query = query.where(peewee.reduce(peewee.operator.or_, where_indices))
# broker
if "brokers" in filter:
where_broker = []
for f in filter["brokers"]:
where_broker.append(StockGroupTicker.stock_index == int(f))
if len(where_broker):
query = query.where(peewee.reduce(peewee.operator.or_, where_broker))
return query.distinct()
SQL Querie (update)
# index and brocker
SELECT
DISTINCT `t1`.`id`,
`t1`.`symbol`,
`t1`.`type`,
`t1`.`name`,
`t1`.`sector`,
`t1`.`region`,
`t1`.`primary_exchange`,
`t1`.`currency`,
`t1`.`score`,
`t1`.`last_price`,
`t1`.`last_price_date`,
`t1`.`last_price_check`,
`t1`.`last_stock_split`,
`t1`.`next_earning`,
`t1`.`last_earnings_update`,
`t1`.`disused`,
`t1`.`source`,
`t1`.`source_intraday`,
`t1`.`created`,
`t1`.`modified`,
`t2`.`invest_score` AS `invest_score`
FROM
`ticker` AS `t1`
INNER JOIN `tickerstats` AS `t2` ON
(`t1`.`id` = `t2`.`ticker_id`)
INNER JOIN `stockgroupticker` AS `t3` ON
(`t1`.`id` = `t3`.`ticker_id`)
WHERE
(((((`t1`.`disused` IS NULL)
OR (`t1`.`disused` = 0))
AND (`t2`.`volume_mean_5` > 10000.0))
AND (`t3`.`stock_index_id` = 1))
AND (`t3`.`stock_index_id` = 10)
)
Thanks to #coleifer, the peewee solution is quite simple. I had to use an alias.
if "indices" in filter and filter["indices"]:
query = query.join(
StockGroupTicker, peewee.JOIN.INNER, on=(Ticker.id == StockGroupTicker.ticker)
)
where_indices = []
for f in filter["indices"]:
where_indices.append(StockGroupTicker.stock_index == int(f))
if len(where_indices):
query = query.where(peewee.reduce(peewee.operator.or_, where_indices))
if "brokers" in filter and filter["brokers"]:
BrokerGroupTicker = StockGroupTicker.alias()
query = query.join(
BrokerGroupTicker, peewee.JOIN.INNER, on=(Ticker.id == BrokerGroupTicker.ticker)
)
where_broker = []
for f in filter["brokers"]:
where_broker.append(BrokerGroupTicker.stock_index == int(f))
if len(where_broker):
query = query.where(peewee.reduce(peewee.operator.or_, where_broker))
return query.distinct()
Related
i would like translate this query :
SELECT DISTINCT backlinks.Source, indexation.date FROM `backlinks` JOIN `indexation` ON backlinks.id = indexation.id_backlinks JOIN positionnement ON backlinks.keyword = positionnement.keyword WHERE positionnement.keyword = %s AND indexation.indexed = 1", (keyword,)
In SQLAlchemy, but i can't.
I try :
select_indexation = db.session.execute(db.select(Backlinks.Source, Indexation.date).filter(Backlinks.id == Indexation.id_backlinks, Backlinks.keyword == Positionnement.keyword, )).all()
select_indexation = db.session.execute(db.select_from(Backlinks).outerjoin(Indexation).filter(Indexation.indexed == 1).outerjoin(Positionnement).filter(Positionnement.keyword == keyword)).all()
subq_1 = db.session.query(Positionnement).\
filter(Positionnement.keyword == keyword).\
subquery()
subq_2 = db.session.query(Indexation).\
filter(Indexation.indexed == 1).\
subquery()
select_indexation = db.session.execute(db.select(Backlinks.Source, Indexation.date).outerjoin(
subq_2, Backlinks.id == subq_2.c.id_backlinks
).outerjoin(
subq_1, Backlinks.keyword == subq_1.c.keyword
)).all()
but i never find the solution.
Have you an idea ?
Thank You
I have this sql
SELECT publishers.id, publishers.created_at, publishers.updated_at, publishers.name,
count(case books.is_active when true then 1 else null end) AS is_active,
count(books.id) as book_count
FROM publishers
LEFT OUTER JOIN books ON books.publisher_id = publishers.id
GROUP BY publishers.id
How i can use this on my python-project with sqlalchemy core?
I have this code now
book_count_alias = models.Book.__table__.alias('book_alias')
join = cls._model.__table__.outerjoin(
models.Book.__table__,
sa.and_(models.Book.publisher_id == models.Publisher.id, models.Book.is_active == True)
).outerjoin(
book_count_alias, book_count_alias.c.publisher_id == models.Publisher.id
)
query = sa.select([cls._model, sa.func.count(models.Book.id).label('is_active'),
sa.func.count(book_count_alias.c.id).label('book_count')])
if q:
query = query.where(cls._model.name.ilike(f'%{q}%'))
query = query.select_from(join).group_by(cls._model.id)
results = await database.fetch_all(query)
return [cls._get_parsed_object(x, schema=schemas.PublisherWithBookCountAndIsActive) for x in results
]
I created my first API where I can get data from my tables in Bigquery.
I can get all the data I need based on the 2 inputs below, but I am also trying to get the whole table when the inputs are empty, which I cannot do.
Thanks for your help
#app.route("/tracking", methods=['GET'])
def tracking_data():
haulier_id_tracking = request.args.get('haulier_id_tracking')
month_tracking = request.args.get('month_tracking')
query_job = bq_client.query("""
WITH t AS (
SELECT *
FROM mart.monthly_vehicle_stats
WHERE dt_fr_month = '{month_tracking}-01' AND (haulier_id_tracking = '{haulier_id_tracking}')
SELECT TO_JSON_STRING(STRUCT(ARRAY_AGG(STRUCT(dt_fr_month, haulier_id_tracking, vehicle_id , nb_days_tracked,
data_access, date_first_camp, invoiced)) AS data)) json
FROM t
""".format(month_tracking = month_tracking, haulier_id_tracking = haulier_id_tracking))
for row in query_job:
return json.loads(row["json"])
You can remove the where clause when the input is empty like this:
#app.route("/tracking", methods=['GET'])
def tracking_data():
haulier_id_tracking = request.args.get('haulier_id_tracking')
month_tracking = request.args.get('month_tracking')
where_clause = ''
if haulier_id_tracking != '' and month_tracking != '':
where_clause = f"WHERE dt_fr_month = '{month_tracking}-01' AND (haulier_id_tracking = '{haulier_id_tracking}'"
query_job = bq_client.query(f"""
WITH t AS (
SELECT * FROM mart.monthly_vehicle_stats {where_clause})
SELECT TO_JSON_STRING(STRUCT(ARRAY_AGG(STRUCT(dt_fr_month, haulier_id_tracking, vehicle_id , nb_days_tracked,
data_access, date_first_camp, invoiced)) AS data)) json
FROM t
""")
for row in query_job:
return json.loads(row["json"])
I'm trying to make a left outer join relation between two tables using joinedload but it doesn't seems to have the same behavior as using outerjoin method.
Here is an example using outerjoin:
stmt = select(ServerFarm)
stmt = stmt.outerjoin(
Server,
(ServerFarm.name == Server.server_farm_id) & (Server.deleted == False)
)
stmt = stmt.filter(ServerFarm.name == name)
print(stmt)
# SELECT ... FROM server_farm
# LEFT JOIN server ON server_farm.name = server.server_farm_id and server.deleted = False
# WHERE server_farm.name = :name
So when I'm using joinedload this is what happens:
stmt = select(ServerFarm)
stmt = stmt.options(
joinedload(
ServerFarm.servers,
(ServerFarm.name == Server.server_farm_id) & (Server.deleted == False)
)
)
stmt = stmt.filter(ServerFarm.name == name)
# SELECT ... FROM server_farm
# LEFT JOIN server ON server_farm.name = server.server_farm_id
# WHERE server_farm.name = :name
On this case, it just ignores the (Server.deleted == False) option. What am I doing wrong? Is there a way to add a "custom" filter on a left outer join using joinedload? How?
I am generating a query with sql alchemy part by part. I have this object that is working very well for a query with only one join:
**I have an ORM model, but I cannot use primary keys setted because are not real.
q = select( self.selectObj._select
).select_from(
self.joinObj._join
).where(
and_(*self.whereObj._where)
).group_by(
*self.selectObj._groupby
).order_by(
self.selectObj._orderby
).limit(
self.selectObj._limit
).having(
self.selectObj._having
)
I have this method for generate the joins:
def get_joins(self, first, leftTable, rightTable, leftTableColumn, rightTableColumn, outer):
if first:
self._join = join(leftTable, rightTable, leftTableColumn == rightTableColumn, full=outer)
first = False
else:
self._join = self._join + join(leftTable, rightTable, leftTableColumn == rightTableColumn, full=outer)
I donĀ“t know, how can I generate, concatenate, get, etc two or more joins for use it in the select_from clause. Any idea?
Thanks a lot in advance :)
The final result should be like this in the from:
SELECT a.dev, b.asha, c.unk
FROM a
FULL OUTER JOIN b ON a.dev = b.devicb
FULL OUTER JOIN c ON a.dev = c.devicc
WHERE
a.cust = 'SNTC' AND
b.cust = 'SNTC' AND
c.cust = 'SNTC' AND
a.invent = '10' AND
b.invent = '10' AND
c.invent = '10'
I solved in this way, just invoquing .join in the previous join but only using right table. self._join.join(rightTable,...)
Complete solution for the method:
def get_joins(self, first, leftTable, rightTable, leftTableColumn, rightTableColumn, outer):
if first:
self._join = join(leftTable, rightTable, leftTableColumn == rightTableColumn, full=outer)
first = False
else:
self._join = self._join.join(rightTable, leftTableColumn == rightTableColumn, full=outer)