Suppose I have this multiple-process Python-MySql query:
self.calculateLeadTime = ("""SET #lastDate = (SELECT sessionDate FROM stock
WHERE product = (%s)
ORDER BY stocksessionID DESC LIMIT 1);
SET #secondLastDate = (SELECT sessionDate FROM stock WHERE product = (%s)
ORDER BY stocksessionID DESC LIMIT 1, 1);
SET #leadTime = (SELECT DATEDIFF(#lastDate, #secondLastDate));
SET #lastStockSessionID = (SELECT stocksessionID
FROM stock WHERE product = (%s) ORDER BY stocksessionID DESC LIMIT 1);
UPDATE stock SET leadTime = (#leadTime)
WHERE stocksessionID = #lastStockSessionID;""", (self.productID.get(), self.productID.get(), self.productID.get()))
self.query = self.cur.execute(self.calculateLeadTime, multi=True)
for self.cur in self.results:
print('cursor:', self.cur)
if self.cur.with_rows:
print('result:', self.cur.fetchall())
self.cn.commit()
I am subject to the error:
stmt = operation.encode(self._connection.python_charset)
AttributeError: 'tuple' object has no attribute 'encode'
I have read the MySql Python documentation regarding multi=True when executing multiple SQL statements via Python. However, my implementation does not work. Any ideas?
Currently, you are passing a tuple as first argument in the cursor.execute call when it expects a single scalar query string in first argument and tuple/list of parameters in second argument:
self.calculateLeadTime = """SET #lastDate = (SELECT sessionDate
FROM stock
WHERE product = (%s)
ORDER BY stocksessionID DESC LIMIT 1);
SET #secondLastDate = (SELECT sessionDate
FROM stock WHERE product = (%s)
ORDER BY stocksessionID DESC LIMIT 1, 1);
SET #leadTime = (SELECT DATEDIFF(#lastDate, #secondLastDate));
SET #lastStockSessionID = (SELECT stocksessionID
FROM stock WHERE product = (%s)
ORDER BY stocksessionID DESC LIMIT 1);
UPDATE stock
SET leadTime = (#leadTime)
WHERE stocksessionID = #lastStockSessionID;
"""
self.query = self.cur.execute(self.calculateLeadTime,
params=(self.productID.get(), self.productID.get(), self.productID.get()),
multi=True)
By the way, MySQL supports JOIN in UPDATE statements for a single statement. Run below with two parameters:
UPDATE stock s
INNER JOIN
(SELECT product, MAX(stocksessionID) AS MaxID
FROM stock
WHERE product = %s
GROUP BY product
) agg_id
ON s.stocksessionID = agg_id.MaxID
INNER JOIN
(SELECT product, MAX(sessionDate) As MaxDate
FROM stock
GROUP BY product) max_dt
ON max_dt.product = s.product
INNER JOIN
(SELECT product, MAX(sessionDate) As SecMaxDate
FROM stock
WHERE sessionDate < ( SELECT MAX(sessionDate)
FROM stock
WHERE product = %s )
GROUP BY product
) sec_max_dt
ON max_dt.product = max_dt.product
SET leadTime = DATEDIFF(MaxDate, SecMaxDate);
I am unsure, if this will work or counts even as multiple queries, because Multi = true is for multiple Resultsets from SELECTS.
You must add teh data for the %s
self.query = self.cur.execute(self.calculateLeadTime,('product','product','product') , multi=True)
Related
How to convert this to peewee query?
_, storage, spaceLeft = db.execute('''
SELECT session, storage, storage - count(questID) FROM Hypos
INNER JOIN Quests ON Hypos.hypoID = Quests.hypoID
WHERE Hypos.hypoID = ?1 AND session = ?2
GROUP BY session
UNION SELECT NULL, max(storage), storage FROM Hypos
WHERE Hypos.hypoID = ?1
ORDER BY session DESC LIMIT 1
''', (body.hypo_id, session)
).fetchone()
I don't understand how to create UNION SELECT in peewee. My attempt:
_, storage, spaceLeft = (db_models.Hypos
.select(db_models.Quests.session, db_models.Hypos.storage, db_models.Hypos.storage-fn.COUNT(db_models.Quests.questID))
.join(db_models.Quests, on=(db_models.Hypos.hypoID == db_models.Quests.hypoID), attr='quests')
.where(db_models.Hypos.hypoID==body.hypo_id, db_models.Quests.session==session)
.group_by(db_models.Quests.session)
) | (db_models.Hypos.select(None, fn.MAX(db_models.Hypos.storage), db_models.Hypos.storage)
.where(db_models.Hypos.hypoID==body.hypo_id)
.order_by(db_models.Quests.session.desc()).limit(1)
)
I got :
1st ORDER BY term does not match any column in the result set
without order_by problem is not enough values to unpack (expected 3, got 2)
Try something like this:
lhs = (Hypo
.select(Quest.session, Hypo.storage, Hypo.storage - fn.COUNT(Quest.questID))
.join(Quest)
.where(
(Hypo.hypoID == hypo_id) &
(Quest.session == session))
.group_by(Quest.session))
rhs = (Hypo
.select(Value(None), fn.MAX(Hypo.storage), Hypo.storage)
.where(Hypo.hypoID == hypo_id))
union = (lhs | rhs).order_by(SQL('1').desc()).limit(1)
_, storage, spaceLeft = union.scalar(as_tuple=True)
The resulting SQL:
SELECT "t1"."session", "t2"."storage", ("t2"."storage" - COUNT("t1"."questID"))
FROM "hypo" AS "t2"
INNER JOIN "quest" AS "t1" ON ("t1"."hypo_id" = "t2"."hypoID")
WHERE (("t2"."hypoID" = ?) AND ("t1"."session" = ?))
GROUP BY "t1"."session"
UNION
SELECT ?, MAX("t3"."storage"), "t3"."storage"
FROM "hypo" AS "t3"
WHERE ("t3"."hypoID" = ?)
ORDER BY 1 DESC LIMIT ?
What I would like returned is all the seat_ids in the performance table that have a booking_id that matches all the booking_ids where night = 1 in the booking table - is an INNER JOIN the best way to do it?
Or is it more along the lines of """SELECT seat_id FROM performance WHERE booking_id=(SELECT * FROM booking WHERE night = ?""", (night_number))
With the above I get sqlite3.OperationalError: incomplete input error.
connection = sqlite3.connect('collyers_booking_system.db')
cursor = connection.cursor()
cursor.execute(booking_table)
cursor.execute(performance_table)
connection.commit()
booking_table = """CREATE TABLE IF NOT EXISTS
booking(
booking_id TEXT PRIMARY KEY,
customer_id INTEGER,
night INTEGER,
cost REAL,
FOREIGN KEY (customer_id) REFERENCES customer(customer_id)
)"""
performance_table = """CREATE TABLE IF NOT EXISTS
performance(
performance_id TEXT PRIMARY KEY,
seat_id TEXT,
booking_id INTEGER,
FOREIGN KEY (seat_id) REFERENCES seat(seat_id),
FOREIGN KEY (booking_id) REFERENCES booking(booking_id),
)"""
night_number = 1
cursor.execute("""SELECT seat_id FROM performance INNER JOIN booking ON night=?""", (night_number))
booked_seats = cursor.fetchall()
print(booked_seats)
With this I get ValueError: parameters are of unsupported type error.
First, if this is your actual code, there is a typo in the CREATE statement of the table performance.
You must remove the , at the end of:
FOREIGN KEY (booking_id) REFERENCES booking(booking_id),
Then, here:
cursor.execute("""SELECT seat_id FROM performance WHERE booking_id=(SELECT * FROM booking WHERE night = ?""", (night_number))
you missed a closing parenthesis for the sql statement and the subquery may return more than 1 rows, so instead of = you should use IN.
Also, the parameter night_number should passed as a tuple and not just a number, by adding a , inside the paraentheses:
cursor.execute("""SELECT seat_id FROM performance WHERE booking_id IN (SELECT * FROM booking WHERE night = ?)""", (night_number,))
For the join you need a proper ON clause, that links the tables and a , to create the tuple for night_number:
sql = """
SELECT p.seat_id
FROM performance p INNER JOIN booking b
ON b.booking_id = p. booking_id
WHERE b.night=?
"""
cursor.execute(sql, (night_number,))
Both ways, the operator IN and the join will work.
There is another option which sometimes performs better and this is EXISTS:
sql = """
SELECT p.seat_id
FROM performance p
WHERE EXISTS (
SELECT 1 FROM booking b
WHERE b.night=? AND b.booking_id = p.booking_id
)
"""
cursor.execute(sql, (night_number,))
You are comparing a list result with an integer.
this SELECT * FROM booking WHERE night = ? => returns an N rows
and you are wating for an Integer SELECT seat_id FROM performance WHERE booking_id=?.
You have to use something like this :
SELECT seat_id FROM performance WHERE booking_id in (SELECT * FROM booking WHERE night = ?""", (night_number))
I am trying to pass data into a nested sqlite3 query in python and I get the following error
Incorrect number of bindings supplied. The current statement uses 2, and there are 1 supplied.
x = uid
sql_query1 = """SELECT title FROM movies WHERE addedBy != ? AND mid NOT IN (SELECT mid FROM ratings WHERE uid = ?);"""
data = (uid, x)
cursor.execute(sql_query1, [data])
movies = cursor.fetchall()
I'm guessing the problem might be that x = uid, I have also tried data = (uid, uid) and cursor.execute(sql_query1, [uid]).
Parameters can be explicitly numbered, and the same value used for all instances of a given number:
sql_query1 = """
SELECT title
FROM movies
WHERE addedBy != ?1 AND mid NOT IN (SELECT mid FROM ratings WHERE uid = ?1);"""
cursor.execute(sql_query1, (uid,))
You need to supply as many parameters as you have question marks.
cursor.execute("""
SELECT title
FROM movies
WHERE addedBy != ?
AND mid NOT IN (SELECT mid FROM ratings WHERE uid = ?);
""", [uid, uid])
movies = cursor.fetchall()
I'd like to get a select by a sub-query but, I don't know how I will do that. I searched for every world of internet but not found what i want.
The select is:
SELECT order_status.*
FROM `order`
LEFT OUTER JOIN
(
SELECT *
FROM (
SELECT *
FROM order_status
ORDER BY created_date DESC LIMIT 1) s
WHERE status IN ('NEW', 'FINISH','SENDED','PROCESSING')
) AS order_status ON order.id = order_status.order_id;
my code:
subqy = self.session.query(OrderStatus).order_by(OrderStatus.created_date.desc()).limit(1).subquery()
query = self.session.query(Order).outerjoin(subqy)
return query.filter(and_(in_(conditions))).all()
I'd change the query a little bit to remove one subquery:
SELECT order_status.*
FROM `order`
LEFT OUTER JOIN
(
SELECT *
FROM order_status
ORDER BY created_date DESC
LIMIT 1
) AS order_status ON order.id = order_status.order_id
AND order_status.status IN ('NEW', 'FINISH','SENDED','PROCESSING')
Then the code becomes
subquery = self.session\
.query(OrderStatus)\
.order_by(OrderStatus.created_date.desc())\
.limit(1)\
.subquery()
query = self.session.query(Order)\
.outerjoin(subquery,
(subquery.c.order_id == Order.id)
& subquery_a.c.status.in_(('NEW', 'FINISH','SENDED','PROCESSING')))
return query.all()
I think the thing you missed is that for subqueries, you need to access the columns through table.c.column, instead of Table.column, as you're used to.
I have this query in python:
ssim_group = [S1200,S1300]
query = '''select WIPMessageCnt from waferdata where recipename in (%s) and equipment = ?
and runtype = ? order by stopts desc limit 1''' % (','.join(ssim_grp))
print query
Current result
select WIPMessageCnt from waferdata where recipename in (S1200,S1460) and equipment = ?
and runtype = ? order by stopts desc limit 1
Expected result should be like this
select WIPMessageCnt from waferdata where recipename in ('S1200','S1460') and equipment = ?
and runtype = ? order by stopts desc limit 1
The list should have single qoutation on each element when I try to put them inside the IN parameter on SQL. How can I achieve this?
ssim_group = ['S1200', 'S1300']
query = '''select WIPMessageCnt from waferdata where recipename in ('%s') and equipment = ? and runtype = ? order by stopts desc limit 1''' % ("','".join(ssim_group))