I have the following SQL statement which works as expected, but I want to do the same thing using the Query API of sqlalchemy, I tried the following but it returns empty. Any idea how I can get this SQL statement by composing the Query API operations?
The raw SQL statement is:
SELECT COUNT(mid), mname
FROM(
SELECT missions._id AS mid, missions.name AS mname
FROM missions
INNER JOIN mission_ownership
ON missions._id = mission_ownership.mission_id
INNER JOIN mission_agencies
ON mission_agencies._id = mission_ownership.mission_agency_id
WHERE mission_agencies.name = 'Nasa'
)
GROUP BY mid
HAVING COUNT(mid) > 1
What I currently have using the ORM Query API:
nasa_and_esa_missions = session.query(func.count(Mission._id), Mission).\
join(mission_ownership). \
join(MissionAgency).\
filter(MissionAgency.name == 'Nasa').\
group_by(Mission._id).\
having(func.count(Mission._id) > 1)
If no relationship has been configured between mission_ownership and mission_agency at the ORM level, this can be done by modelling the inner SELECT as a subquery:
subq = (session.query(Mission._id.label('mid'), Mission.name.label('mname'))
.join(mission_ownership)
.join(MissionAgency)
.filter(MissionAgency.name == 'Nasa')
.subquery())
q = (session.query(subq.c.mid, Mission)
.group_by(subq.c.mid)
.having(sa.func.count(subq.c.mid) > 1))
for id_, m in q:
print(id_, m.name)
Which generates this SQL:
SELECT anon_1.mid AS anon_1_mid, missions._id AS missions__id, missions.name AS missions_name
FROM (SELECT missions._id AS mid, missions.name AS mname FROM missions
JOIN mission_ownership ON missions._id = mission_ownership.mission_id
JOIN mission_agencies ON mission_agencies._id = mission_ownership.mission_agency_id
WHERE mission_agencies.name = ?) AS anon_1, missions
GROUP BY anon_1.mid
HAVING count(anon_1.mid) > ?
Related
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'm creating an application with a flask backend and I'm using SQLAlchemy Core to create the SQL-Queries. Now I'm creating a base select like this:
SYSTEM = self.__TABLES.SYSTEM
RESPONSIBLE = self.__TABLES.responsible
INFRA_RESPONSIBLE = RESPONSIBLE.alias('INFRA_RES')
SYSTEM_RESPONSIBLE = RESPONSIBLE.alias('SYS_RES')
STMT = SYSTEM \
.outerjoin(INFRA_RESPONSIBLE, INFRA_RESPONSIBLE.c.id == SYSTEM.c.infrares) \
.outerjoin(SYSTEM_RESPONSIBLE, SYSTEM_RESPONSIBLE.c.id == SYSTEM.c.sysres)
Now, if I'm creating a SQL-Query like this:
STMT = select([SYSTEM]) \
.select_from(STMT) \
.where(INFRA_RESPONSIBLE.c.id == 1)
This is how the generated looks like:
SELECT "it".systems.*
FROM "it".responsible AS "INFRA_RES", "it".systems
LEFT OUTER JOIN "it".responsible as "INFRA_RES" ON "INFRA_RES".id = "it".systems.infrares
LEFT OUTER JOIN "it".responsible as "SYS_RES" ON "SYS_RES".id = "it".systems.sysres
WHERE "INFRA_RES".id = 1
But i want to look it like this:
SELECT "it".systems.*
"it".systems
LEFT OUTER JOIN "it".responsible as "INFRA_RES" ON "INFRA_RES".id = "it".systems.infrares
LEFT OUTER JOIN "it".responsible as "SYS_RES" ON "SYS_RES".id = "it".systems.sysres
WHERE "INFRA_RES".id = 1
The table INFRA_RES is already joined with the base statement, how can I achieve to build a proper SQL-Statement?
The query I want to convert looks like this:
SELECT
sum(CASE
WHEN (countryCd3 = (
SELECT
countryCd3 as id2
FROM myTable
where a.countryCd3 = id2
GROUP BY countryCd3
HAVING count(countryCd3) > 1) AND countryCd3 IS NOT NULL) THEN 1 ELSE 0
END) AS unexpected_count
FROM myTable as a;
This is in Teradata and it works. The issue I have is converting this to sqlalchemy, especially passing there where line with the appropriate aliases.
What I have tried so far:
import sqlalchemy as sa
table_outer = sa.table('myTable', sa.column('countryCd3'))
table_inner = sa.table('myTable', sa.column('countryCd3'))
inner_query = (sa.select([sa.column(column)])
.where(table_outer.c.id == table_inner.c.id)
.select_from(table_inner)
.group_by(sa.column(column))
.having(sa.func.count(sa.column(column)) > 1))
print(inner_query)
Output:
SELECT countryCd3
FROM "myTable", "myTable"
WHERE "myTable".countryCd3 = "myTable".countryCd3 GROUP BY countryCd3
HAVING count(countryCd3) > :count_1
Haven't tried to construct the outer query given this issue currently.
Any ideas for how I could do a nested join using SQLAlchemy? Here is the raw query I am trying to recreate.
SELECT "tblLinkDivisions"."DivisionCoLinkID", 5 AS Score, "tblCompanies"."CompanyID"
FROM "tblS_AppliedStrategy"
INNER JOIN
(
(
"tblLinkIndustry" INNER JOIN "tblLinkDivisions" ON "tblLinkIndustry"."IndustryCoLinkID" = "tblLinkDivisions"."IndustryCoLinkID"
)
INNER JOIN "tblLinkAppliedStrategy"
ON "tblLinkDivisions"."DivisionCoLinkID" = "tblLinkAppliedStrategy"."DivisionCoLinkID"
)
ON "tblS_AppliedStrategy"."AppStrategyCode" = "tblLinkAppliedStrategy"."AppStrategyCode"
INNER JOIN "tblCompanies" ON ("tblCompanies"."CompanyID" = "tblLinkIndustry"."CompanyID" AND "tblCompanies"."CompanyID" != %s)
WHERE "tblS_AppliedStrategy"."AppStrategyCode" IN %s
I have tried a few different solutions with this being the closest outcome:
companies = (
session.query(tblLinkDivisions.DivisionCoLinkID, tblCompanies.CompanyID)
.select_from(tblS_AppliedStrategy)
.join(tblLinkIndustry, tblLinkDivisions.IndustryCoLinkID == tblLinkIndustry.IndustryCoLinkID)
.join(tblLinkAppliedStrategy, tblLinkDivisions.DivisionCoLinkID == tblLinkAppliedStrategy.DivisionCoLinkID)
.join(tblLinkAppliedStrategy, tblS_AppliedStrategy.AppStrategyCode == tblLinkAppliedStrategy.AppStrategyCode)
.join(tblCompanies, and_(tblCompanies.CompanyID == tblLinkIndustry.CompanyID, tblCompanies.CompanyID != company_id))
.filter(tblS_AppliedStrategy.AppStrategyCode.in_(strategy))
.all()
)
Any help or suggestions would be greatly appreciated!
I am running this on pymysql and it appears to have a syntax problem although on workbench if i repace %s with a random value it works fine.What am I doing wrong?Also the full error row is this ProgrammingError(1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '3226'') \n GROUP BY a2.actor_id=''3226'',a1.actor_id \n HAVING count(DISTINC' at line 9")
sql_query='''SELECT a1.actor_id as i8opoios1 FROM actor as a1
INNER JOIN actor as a2 on a1.actor_id != a2.actor_id
INNER JOIN role as r1 on a1.actor_id = r1.actor_id
INNER JOIN movie as m1 on m1.movie_id = r1.movie_id
INNER JOIN movie_has_genre as mg1 on mg1.movie_id = m1.movie_id
INNER JOIN role as r2 on a2.actor_id = r2.actor_id
INNER JOIN movie as m2 on m2.movie_id = r2.movie_id
INNER JOIN movie_has_genre as mg2 on mg2.movie_id = m2.movie_id
WHERE (a2.actor_id='%s')
GROUP BY a2.actor_id='%s',a1.actor_id
HAVING count(DISTINCT mg1.genre_id) + count(DISTINCT mg2.genre_id)>=7
AND SUM(mg1.genre_id = mg2.genre_id) = 0'''
cur.execute(sql_query,(actorId,actorId))
results=cur.fetchall()