On what page is my row displayed? - python

I have a table of posts. I display the list of posts paginated organized by time descending with each page limited to 20 rows. How do I figure out what page a specific row is by id is on so I can link to that specific page.
Table post
CREATE TABLE post
(
id serial NOT NULL,
text character varying(1000),
created_date timestamp without time zone,
CONSTRAINT post_pkey PRIMARY KEY (id)
)
Current
select * from post order by created_date desc limit 20 offset 0
What page is id X on? My theory is I can return the row number the id is on when you select by the specific 'order by' but I'm not sure if that's right or how to do that.

I suggest the window function row_number() in a subquery:
SELECT rn / 20 + 1 AS page -- 20 rows per page
FROM (
SELECT id, row_number() OVER (ORDER BY created_date DESC) AS rn
FROM post
) sub
WHERE id = 123;
The usual disclaimer: page numbers can change if underlying data changes (concurrently).

If you want a single link and if the created_date is always the inserting current_timestamp then it can be done counting the serial id
select count(*) / 20 + 1 as page
from post
where id >= %(id)s
To make it easier to always have the current_timestamp as the created_date make it the default
created_date timestamp default current_timestamp
It is possible to make it a constraint
created_date timestamp default current_timestamp check(created_date = current_timestamp)
If you need a list of links pass the ids as a Python list to the query
select *
from (
select id, count(*) over(order by id desc) / 20 + 1 as page
from post
where
id >= (
select id
from unnest(%(ids_list)s) s
order by id
limit 1
)
) s
where id = any (%(ids_list))s
In this last query count is a running total.
SQL Fiddle

Related

sql insert query with select query using pythonn and streamlit

i have an sql insert query that take values from user input and also insert the ID from another table as foreign key. for this is write the below query but it seems not working.
Status_type table
CREATE TABLE status_type (
ID int(5) NOT NULL,
status varchar(50) NOT NULL
);
info table
CREATE TABLE info (
ID int(11) NOT NULL,
name varchar(50), NULL
nickname varchar(50), NULL
mother_name varchar(50), NULL
birthdate date, NULL
status_type int <==this must be the foreign key for the status_type table
create_date date
);
for the user he has a dropdownlist that retrieve the value from the status_type table in order to select the value that he want to insert into the new record in the info table
where as the info table take int Type because i want to store the ID of the status_type and not the value
code:
query = '''
INSERT INTO info (ID,name,nickname,mother_name,birthdate,t1.status_type,created_date)
VALUES(?,?,?,?,?,?,?)
select t2.ID
from info as t1
INNER JOIN status_type as t2
ON t2.ID = t1.status_type
'''
args = (ID,name,nickname,mother_name,db,status_type,current_date)
cursor = con.cursor()
cursor.execute(query,args)
con.commit()
st.success('Record added Successfully')
the status_type field take an INT type (the ID of the value from another table ).
So when the user insert it insert the value.
What i need is to convert this value into its corresponding ID and store the ID
based on the answer of #Mostafa NZ I modified my query and it becomes like below :
query = '''
INSERT INTO info (ID,name,nickname,mother_name,birthdate,status_type,created_date)
VALUES(?,?,?,?,?,(select status_type.ID
from status_type
where status = ?),?)
'''
args = (ID,name,nickname,mother_name,db,status_type,current_date)
cursor = con.cursor()
cursor.execute(query,args)
con.commit()
st.success('Record added Successfully')
When creating a record, you can do one of these ways.
Receive as input from the user
Specify a default value for the field
INSERT INTO (...) VALUES (? ,? ,1 ,? ,?)
Use a select in the INSERT
INSERT INTO (...) VALUES (? ,? ,(SELECT TOP 1 ID FROM status_type ODER BY ID) ,? ,?)
When INSERT data, you can only enter the names of the destination table fields. t1.status_type is wrong in the following line
INSERT INTO info (ID,name,nickname,mother_name,birthdate,t1.status_type,created_date)

Python/MySQL SELECT, Update and Fetch in same query

I want to SELECT and UPDATE in one query.
In my database, I have category_ids that needs to be checked. I want to select the last updated query by DESC and update it with runs = runs+1, so it counts up that and also automatically update the last_update field.
But for some reason, I can't fetch it
cursor.execute(
"UPDATE categorys as t1,
(SELECT category_id
FROM categorys
ORDER BY last_update
LIMIT 1) as t2
SET t1.runs = t1.runs+1
WHERE t2.category_id = t1.category_id")
row = cursor.fetchone()
print(row)
print(row) gives me None but I need the category_id here
The update works and counts up the runs+1 of the last_update DESC
mysql update doesn't return value of data changed. It only returns the Query ran ok.
you would need to execute the select statement to return the category_id.

SQLALCHEMY: Problem with subquery select, How do i a exact subquery with outerjoin?

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.

How to use a subquery as a column in query using flask_SQLAlchemy?

I have a table in my database with four columns: ID, task_name, due_date, completed_date
I am trying to use a subquery as one of output columns.
Here is the SQL, which works fine:
SELECT
due_date AS date,
COUNT(id) AS tasks_due,
( SELECT COUNT(id) FROM task_data WHERE completed_date IS NOT NULL AND due_date = T.due_date ) as tasks_completed,
FROM task_data T
GROUP BY date
ORDER BY date
The issue I am having is trying getting translate this bit into a SQLAlchemy query due_date = T.due_date
UPDATE I've managed to work it out. Code below, for anyone who is interested.
completed_tasks = (db.session.query(
Task.due_date, db.func.count(Task.id).label('tasks_completed'))
.filter(Task.completed_date != None)
.group_by(Task.due_date).subquery()
)
task_query = (db.session.query(
Task.due_date.label('date'),
db.func.count(Task.id).label('tasks_due'),
completed_tasks.c.tasks_completed.label('tasks_completed'))
.outerjoin(completed_tasks, Task.due_date == completed_tasks.c.due_date)
.group_by(Task.due_date, completed_tasks.c.tasks_completed)
.order_by(Task.due_date)
)

Why does the loop run more than once?

I apologize for posting so much code, I couldn't get the behavior to repeat on an abstracted simplified program so I had to post the actual code.
The goal is for the contents of the cart table to be placed in the orders and odetails table.
What is actually happening is that if there is one entry in the cart there will be more than ten entries in the orders tables. The way I see the for loops that execute after insertSql is that it will run through the entire loop once and exit on the break. That is, it executes insertSql then it retrieves the order number ono then it sets the class attribute orderNumber to the retrieved order number ono and sets the cart to empty. What am I missing?
I am using Python 2.7 and the modules cmd and cx_Oracle.
def oneClick(self,userLoggedIn):
#this checks if there is a credit card available, if there isn't it denies one click check out
sql = """
SELECT creditcardnumber, creditcardtype
FROM bs_members
WHERE userid = :userid
"""
ds.execute(sql,userid=userLoggedIn)
for row in ds:
if row == (None,None):
print """
One click check out is not available if you do not have a credit card on file.
"""
else:
break
#this checks to see if the user has anything in the cart
cartSql = """
SELECT DISTINCT userid FROM bs_cart WHERE userid = :userid
"""
ds.execute(cartSql,userid=userLoggedIn)
#this places the contents of the cart into the order tables
insertSql = """
BEGIN
INSERT INTO bs_orders (userid, ono, timePurchased)
VALUES (:userid, orderNum_seq.NEXTVAL,(SELECT current_timestamp FROM dual));
COMMIT;
UPDATE bs_orders
SET shipaddress = (SELECT address FROM bs_members WHERE userid = :userid)
, shipcity = (SELECT city FROM bs_members WHERE userid = :userid)
, shipstate = (SELECT state FROM bs_members WHERE userid = :userid)
, shipzip = (SELECT zip FROM bs_members WHERE userid = :userid)
WHERE userid = :userid
AND timePurchased IN
(
SELECT MAX(timePurchased)
FROM bs_orders
WHERE userid = :userid
GROUP BY userid
);
INSERT INTO bs_odetails (ono, isbn, qty, price)
SELECT orderNum_seq.CURRVAL, bs_cart.isbn, bs_cart.qty, bs_books.price
FROM bs_orders, bs_cart, bs_books
WHERE bs_orders.userid = :userid
AND bs_cart.userid = :userid
AND bs_books.isbn = bs_cart.isbn;
DELETE FROM bs_cart
WHERE userid = :userid;
END;
"""
#if the cart has contents this for loop is executed
for row in ds:
ds.execute(insertSql,userid=userLoggedIn)
sql = """
SELECT ono
FROM bs_orders
WHERE userid = :userid
AND timePurchased IN
(
SELECT MAX(timePurchased)
FROM bs_orders
WHERE userid = :userid
GROUP BY userid
)
"""
ds.execute(sql,userid=userLoggedIn)
for row in ds:
self.orderNumber = ''.join(str(i) for i in row)
self.cartIsEmpty = False
break
#if the cart does not have any contents the user is told to try again
else:
print """
You have nothing in your cart!
"""
self.cartIsEmpty = True

Categories

Resources