Trying not to hardcode date range in SQL query (Python, SQL server) - python

I am using Python to connect to SQL Server database and execute several 'select' type of queries that contain date range written in a particular way. All these queries have the same date range, so instead of hard-coding it, I'd prefer to have it as a string and change it in one place only when needed.
So far, I found out that I can use datetime module and the following logic to convert dates to strings:
from datetime import datetime
start_date = datetime(2020,1,1).strftime("%Y-%m-%d")
end_date = datetime(2020,1,31).strftime("%Y-%m-%d")
Example of the query:
select * from where xxx='yyy' and time between start_date and end_date
How can I make it work?
EDIT
my code:
import pyodbc
import sqlalchemy
from sqlalchemy import create_engine
from datetime import datetime
start_date = datetime(2020,1,1).strftime("%Y-%m-%d")
end_date = datetime(2020,1,31).strftime("%Y-%m-%d")
engine = create_engine("mssql+pyodbc://user:pwd#server/monitor2?driver=SQL+Server+Native+Client+11.0")
sql_query = """ SELECT TOP 1000
[mtime]
,[avgvalue]
FROM [monitor2].[dbo].[t_statistics_agg]
where place = 'Europe' and mtime between 'start_date' and 'end_date'
order by [mtime] asc;"""
df = pd.read_sql(sql_query, engine)
print(df)

Thank you all for your input, I have found the answer to make the query work. The variables should look like:
start_date = date(2020, 1, 1)
end_date = date(2020, 1, 31)
and SQL query like:
sql_query = f""" SELECT TOP 1000
[mtime]
,[avgvalue]
FROM [monitor2].[dbo].[t_statistics_agg]
where place = 'Europe' and mtime between '{start_date}' and '{end_date}'
order by [mtime] asc;"""

Related

How to select dates in SQLite with python

Im trying to query a table, and need to grab all products that have a date = today date.
Below is my code so far
import sqlite3
from datetime import date
date = date.today()
con = sqlite3.connect('test.db')
cur = con.cursor()
date = date.today()
sql_q = f'''SELECT date, name FROM table WHERE date = {date}'''
table = cur.execute(sql_q)
for row in table:
print(row)
i am using an SQlite 3 db and all data has been entered with the following format:
2022-09-20
However this variable type does not seem to work with SQL.
i know the SQL code should look somthing like this
SELECT name FROM test WHERE date = '2022-09-20'
but i'd like the date to be selected automatically from python rather than typing it in manually.
Use the function date() to get the current date:
SELECT name FROM test WHERE date = date()
or CURRENT_DATE:
SELECT name FROM test WHERE date = CURRENT_DATE
I think you need to convert date to string and then pass it in query.
maybe your datatype of column and date.today() is different.
date = date.strftime('%Y-%m-%d')
try using this.

Need to automate the Start_date and End_date in Python from Oracle database

I'm new to Python and I'm interested to switch to Python all my current reporting's. As my reports include date frames, mostly of my reports include in the SQL query a "Start_Date" and an "End_Date". I have been looking around on how to write some line of code to do the same in python. Has anyone experienced the same, please help and share. My code is as follows:
import pandas as pd
import numpy as np
import cx_Oracle
import warnings
from datetime import date
from datetime import datetime as dtt
connstr = 'UN/PW#dbpath/DB' # this is hidden due to security
conn = cx_Oracle.connect(connstr)
today=date.today()
start_date = input("Enter start_date in MM/DD/YYYY format :")
month, year, day = map(int, start_date.split('/'))
end_date= input("Enter end_date in MM/DD/YYYY format :")
month, year, day = map(int, end_date.split('/'))
# a pop up will require to enter the start_date and the end_date manually
print (start_date)
print (end_date)
05/01/2021
05/31/2021
df=pd.read_sql_query("""select pr_no
, pr_task_no
, to_date(to_char(act_complete_date_time,'mm/dd/yyyy'),'mm/dd/yyyy') as act_complete_date_time
from pr_task
where pr_task_no = 100
and act_complete_date_time between to_date({start_date},'mm/dd/yyyy') and to_date({end_date},'mm/dd/yyyy')
""", conn)
The error that I'm getting is: DatabaseError: Execution failed on sql
': ORA-00936: missing expression
So Oracle is not recognizing the date entered and is not running the script.
I have give multiple attempts to format the date so it can be recognized from the database.
Can someone help to achieve this step?
Thank you in advance!
i think you are missing a "f" before the query string, as is
df=pd.read_sql_query(f"""select pr_no
, pr_task_no
, to_date(to_char(act_complete_date_time,'mm/dd/yyyy'),'mm/dd/yyyy') as act_complete_date_time
from pr_task
where pr_task_no = 100
and act_complete_date_time between to_date({start_date},'mm/dd/yyyy') and to_date({end_date},'mm/dd/yyyy')
""", conn)
without it you are sending the literal {start_date} to the db as the query and it is not replaced with the variable with the same name
as a side note, this code is considered vulnrable if you are letting an unknown user set the times, he or she could use sql injection to edit you query (imagine if instead of a date they put ;drop table pr_task)

In Python I have embedded SQL code with 2 sets of between dates. How to loop the python code to run multiple sets of between dates

I am new to this so sorry if my question is odd or confusing. In python I have an embedded SQL query that has 2 between dates for data. I have several dates I want to loop this code through each 'between date sets' I have for the entire month. I feel like I am missing a package that would help with this and I have not found a tutorial to follow something like this.
Say for example sake.
List of between dates
2020-02-01 AND 2020-02-05,
2020-02-02 AND 2020-02-06,
2020-02-03 AND 2020-02-07,
... all the way to ...
2020-02-28 AND 2020-03-04
Where I am at so far is this and I can't figure out how to setup an array for this.
import psybopg2
import getpass
import pandas
con = psybopg2.connect(host="blah",database="blah",user=getpass.getpass
cur.execute("""
SELECT
Address
,Create_Data
,Event_Date
FROM
table.a
WHERE
Create_Date between '2020-03-20' AND '2020-03-25' --(want to insert set of dates from the list
AND
Event_Date between '2020-03-20' AND '2020-03-25' --(want to insert the same between date used above
""")
output = cur.fetchall ()
data = pd.DataFrame(output)
cur.close()
con.close()`
Use datetime and timedelta:
from datetime import datetime
start_date = "2020-02-01"
stop_date = "2020-02-28"
start = datetime.strptime(start_date, "%Y-%m-%d")
stop = datetime.strptime(stop_date, "%Y-%m-%d")
from datetime import timedelta
while start < stop:
first_date = start #first date for between
second_date = start + timedelta(days=4) #second date for between
#Use the above in sql query
start = start + timedelta(days=1) # increase day one by one

How can I get the amount of days between two dates?

I got a python script, which is supposed to fetch data of my mysql table (contains a date) and then it should print out the amount of days between today´s date and the date of my mysql table.
I already tried substracting the two dates, but this wouldn´t work. So I tried substracting today´s date and my birthday, which worked. So I think the problem is the mysql date.
import datetime
import mysql.connector
mydb = mysql.connector.connect(
host="localhost",
user="root",
passwd="",
database='appointments'
)
eventDate = mydb.cursor()
eventDate.execute('SELECT event_date FROM appointdatetitle')
Date = eventDate.fetchall()
tdelta = datetime.timedelta(days=7)
today = datetime.date.today()
eday = Date
till_eday = eday - today
print(till_eday.days)
Date = eventDate.fetchall() fetchall actually fetches a tuple of tuples
e.g.
(('abcd',), ('efgh',))
You would want to get the Date by looping over the list and getting the elements. e.g.
for d in Date:
#This will contain the date you need
print(d[0])
Or you can directly access an element by doing say Date[0][0]
After update from OP, this is what can be done!
OP can use https://dateutil.readthedocs.io/en/stable/index.html to use the
from dateutil.relativedelta import * to increment the month!
import datetime
from dateutil.relativedelta import *
Date = [(datetime.date(2019, 4, 24),)]
#Extract actual datetime object from Date variable
date_obj = Date[0][0]
#Increment month by 1 since January starts from 0
date_obj += relativedelta(months=1)
today = datetime.date.today()
#Using datetime from above
eday = date_obj
till_eday = eday - today
print(till_eday.days)
The output will be 23

Oracle to_date within SQLAlchemy query

Using plain Oracle SQL, I would use:
select *
from mytable
where
to_date(date_d, 'dd-mon-yyyy') == to_date('01-Jan-2013', 'dd-mon-yyyy')
Now using SQLAlchemy, I'm at a loss.
from datetime import datetime
dt = myTable.c.date_d == datetime(2013, 1, 1)
q = session.query(myTable).filter(dt)
q.first()
Will give me incorrect results, because date_d is varchar, so it won't translate to date unless I run an Oracle function to convert the datatype within the query. How can I do that?
Turns out I didn't need to convert the datatype. SQLAlchemy seems to do that transparently. However, If I feel like doing it explicitly:
from sqlalchemy import func
dt = func.to_date(myTable.c.date_d, 'dd-mon-yyyy') == datetime(2013, 1, 1)
q = session.query(dt)
q.first()
My incorrect results were due to an unrelated mistake.

Categories