Searching a date with parameter 'LIKE' - python

I am building a small program in Python and SQlite where a client can type a date in the format YYYY-MM-DD and get back all the plays that take place in that specific date. All the plays are store in Play.db which saves the date as: YYYY-MM-DD HH:MM
I do not want the user to type the exact date with hour and minutes. He just has to type the year-month-day and all the plays in that specific date should appear.
I realise that I need the keyword 'LIKE' and pass my variable between '%'variable'%' in order to get a similar (not exact) match.
However I am not sure how to do so by using the syntax of my SQLite query:
user_input = input("Please, type the date of the play in format: 'YYYY-MM-DD':")
search_date = """SELECT * FROM play WHERE play_date LIKE ? """
cursor.execute(search_date, [(user_input)])
results = cursor.fetchall()
The issue is that 'results' is not populated because the SQL query is looking for exact match.
THEREFORE I tried with %user_input% or %?% but, obsiously, the variable '%user_input%' or %?% is not defined.
I understand how logically is should be done:
how to search similar strings in SQLite
But I am not sure how the "LIKE '%'variable'%'" can be obtained using my code syntax.

import datetime
user_input = datetime.datetime(input("Please, type the date of the play in format: 'YYYY-MM-DD':"), '%Y-%m-%d')
# 2011-11-11
search_date = f'SELECT * FROM play WHERE play_date LIKE {user_input}'
print(search_date)
# SELECT * FROM play WHERE play_date LIKE 2011-11-11
Is this what you're looking for?
Edited to prevent sql injections

Use the date function in your query to just compare the dates of your stored datetime values and user input.
SELECT * FROM play WHERE date(play_date) = date(?)

You need a date function. Also you can use slicing for the string. Like:
theDate = input() #example: 2018-12-24
Year = theDate[:3]
Month = theDate[5:6]
Day = theDate[8:9]

Good day,
Well it may not be exactly what you want but I would share you some pieces of code I wrote when I wanted to build something like this but this time using Flask and SQLAlchemy.
First is to convert the data to a date/datetime to ensure the data is valid
converted_date = datetime.datetime.strptime(user_input, "%Y-%m-%d").date()
Converted to regular SQL query should be
SELECT * FROM play WHERE play_date LIKE {"%" + converted_date}
Please note that the "%" is very important, and putting it at the beginning means you want to search for any date that starts with the inputted date.

Related

Date matching not working on date and object?

I have a variable which holds a date inputted by the user and converts it to date format using this code:
correct_date = "2022-06-08"
correct_date = dt.datetime.strptime(correct_date,'%Y-%m-%d').date()
I also have some embedded SQL in the same script that returns dates in YYYY-MM-DD format; these are saved into a dataframe:
actual_dates = pd.read_sql_query(
sql = f"""
SELECT DATE(CONTACTDATETIME) AS CONTACT_DATE
FROM TABLE1
GROUP BY DATE(CONTACTDATETIME);
""",
con = connection)
If work carried out elsewhere was done correctly, there should only be one date in the results from the SQL, which should match the date that was entered into the correct_date variable.
What I want to do is check whether this is the case. I have the code below to do this, but the problem is it always returns FAIL even when the only value in actual_dates matches correct_date.
if actual_dates["contact_date"].any() != correct_date:
print("FAIL")
else:
print("SUCCESS")
Does anyone know where I may be going wrong please? I have the suspicion it's because Python doesn't recognise a date and an object as being the same thing even when they're in YYYY-MM-DD format. Is this correct and if so does anyone know how I can work around this to achieve the required result please?
In above case, you are comparing 'String' with Date object. which will always return False.
Instead, converting the string to Date, and then comparing will give correct result.
Check below code.
if datetime.datetime.strptime(actual_dates["contact_date"],'%Y-%m-%d').date() != correct_date:
print("FAIL")
else:
print("SUCCESS")

Save a new entity (play) only if there is not a clash of date and time

I am building a booking system in Python and SQLite.
I have a Staff.db and Play.db (one-to-many relationship).
The idea is the following: the only staff member of the theater can choose when to add a play by specifying its starting date and time. I saved the date/time in the Play.db as string 'YYYY-MM-DD HH:MM'.
However, since the theater has only one room, the staff member can add the play only if its time 'YYYY-MM-DD HH:MM' does not clash with already existing plays.
Important information: each play lasts 1 hour only.
My question:
How can I create a python function or SQLite query to allow the staff member to add the new play only when it does not class with already existing plays?
I realized two things:
I have to get the starting date of each play
To this starting date, I have to add +1 hour so that I know if this 'period' is free
The issue is that I tried unsuccesfully some queries with SQL but I am not really sure how to approach this problem.
Something like this should work (I would think):
import datetime
now = datetime.datetime.now()
next_hour = now + datetime.timedelta(hours=1)
now = now.strftime('%Y-%m-%d %H:%M')
next_hour = next_hour.strftime('%Y-%m-%d %H:%M')
query = ("SELECT COUNT(*) FROM mytable WHERE "
"play_start >= %s AND plan_start <= %s" % (now, next_hour))
# If the query value is larger than 0, you have a clash
Of course, this example uses now() as the lookup time. You would clearly substitute the actual time being searched, but I used now() as an example.

Python - Filtering SQL query based on dates

I am trying to build a SQL query that will filter based on system date (Query for all sales done in the last 7 days):
import datetime
import pandas as pd
import psycopg2
con = p.connect(db_details)
cur = con.cursor()
df = pd.read_sql("""select store_name,count(*) from sales
where created_at between datetime.datetime.now() - (datetime.today() - timedelta(7))""",con=con)
I get an error
psycopg2.NotSupportedError: cross-database references are not implemented: datetime.datetime.now
You are mixing Python syntax into your SQL query. SQL is parsed and executed by the database, not by Python, and the database knows nothing about datetime.datetime.now() or datetime.date() or timedelta()! The specific error you see is caused by your Python code being interpreted as SQL instead and as SQL, datetime.datetime.now references the now column of the datetime table in the datetime database, which is a cross-database reference, and psycopg2 doesn't support queries that involve multiple databases.
Instead, use SQL parameters to pass in values from Python to the database. Use placeholders in the SQL to show the database driver where the values should go:
params = {
# all rows after this timestamp, 7 days ago relative to 'now'
'earliest': datetime.datetime.now() - datetime.timedelta(days=7),
# if you must have a date *only* (no time component), use
# 'earliest': datetime.date.today() - datetime.timedelta(days=7),
}
df = pd.read_sql("""
select store_name,count(*) from sales
where created_at >= %(latest)s""", params=params, con=con)
This uses placeholders as defined by the psycopg2 parameters documentation, where %(latest)s refers to the latest key in the params dictionary. datetime.datetime() instances are directly supported by the driver.
Note that I also fixed your 7 days ago expression, and replaced your BETWEEN syntax with >=; without a second date you are not querying for values between two dates, so use >= to limit the column to dates at or after the given date.
datetime.datetime.now() is not a proper SQL syntax, and thus cannot be executed by read_sql(). I suggest either using the correct SQL syntax that computes current time, or creating variables for each datetime.datetime.now() and datetime.today() - timedelta(7) and replacing them in your string.
edit: Do not follow the second suggestion. See comments below by Martijn Pieters.
Maybe you should remove that Python code inside your SQL, compute your dates in python and then use the strftime function to convert them to strings.
Then you'll be able to use them in your SQL query.
Actually, you do not necessarily need any params or computations in Python. Just use the corresponding SQL statement which should look like this:
select store_name,count(*)
from sales
where created_at >= now()::date - 7
group by store_name
Edit: I also added a group by which I think is missing.

How to modify the input value of a stored procedure with python

Currently, I am trying to modify two input values of the following stored procedure that I execute with Python.
country_cursor.execute(
"[DEV].[DevelopmentSchema].[QA_Extractor] #start_date='2017-05-05', #end_date='2017-05-11'")
I do not want to run this program every day and change the start_date and end_date manually from the code but instead trying to create a prompt where I can type down the dates that I want to look for the retrieval.
So far, I have done the following:
end_date = str(datetime.now()).rpartition(' ')[0]
start_date = str(datetime.now() - timedelta(days=7)).rpartition(' ')[0]
country_cursor.execute(
"[DEV].[DevelopmentSchema].[QA_Extractor] #start_date='2017-05-05', #end_date= "+"'"+end_date+"'"+"\"")
I just replaced one input date with a variable but when I execute this program I encounter the following SQL error:
pypyodbc.ProgrammingError: ('42000', '[42000] [Microsoft][ODBC SQL Server
Driver][SQL Server]An object or column name is missing or empty. For SELECT
INTO statements, verify each column has a name. For other statements, look
for empty alias names. Aliases defined as "" or [] are not allowed. Change
the alias to a valid name.')
My point of view is that the Stored Procedure does not accept this variable as the end date, in consequence, the column to look for the retrieval does not exist. I also read in SQL Server query erroring with 'An object or column name is missing or empty' which supports my view. Am I right with my thinking or am I totally wrong?
How can I fix this problem? Any ideas, suggestions and improvements are welcome ;)
If I do this:
print("[DEV].[DevelopmentSchema].[QA_Extractor] #start_date='2017-05-05', #end_date= "+"'"+end_date+"'"+"\"")
I get this:
[DEV].[DevelopmentSchema].[QA_Extractor] #start_date='2017-05-05', #end_date= '2017-05-14'"
It seems to me that there is a stray " at the end of this query string.
Part of the problem is that you are working way too hard to format the dates as strings.
I am guessing that there is
from datetime import *
at the top of your code (ugly, but hardly your fault). If so, you can do
start_date = datetime.now() - timedelta(days=7)
end_date = datetime.now()
query_string = f"[DEV].[DevelopmentSchema].[QA_Extractor] #start_date='{start_date:%Y-%m-%d}', #end_date='{end_date:%Y-%m-%d'}"
country_cursor.execute(query_string)
which arguably makes it easier to see stray punctuation.

python sql where using dates

I am trying to get all records that are within the current week(monday to sunday) and then I was planning to insert them back into the database but with the date of lesson being increased by 7. However I get the following error:
sqlite3.OperationalError: near ">=": syntax error
I may be wrong but I think that this is due to how python stores dates is there a way around this, if not I can always get all records in table into array and filter that array in python. The code for the sql is underneath:
with sqlite3.connect("GuitarLessons.db") as db:
cursor = db.cursor()
cursor.row_factory = sqlite3.Row
sql = "select *"\
"from tblBookings"\
"where DateOfLesson >= ?"\
"and DateOfLesson <= ?"
cursor.execute(sql,(startweekd,endweekd))
BookingList = cursor.fetchall()
print(BookingList)
The rest of my code is just calculating the start and end date for that week.
import datetime
from datetime import date, timedelta
import sqlite3
tdate = datetime.datetime.today()
tday = datetime.datetime.today().weekday()
tdadd = 7 - (tday+1)
endweekd = date.today() + timedelta(days=tdadd)
startweekd = endweekd - timedelta(days=7)
endweekd = endweekd.strftime("%d/%m/%y")
startweekd = startweekd.strftime("%d/%m/%y")
print(startweekd)
print(endweekd)
SQLite (nowhere, not just in Python) does not support dates.
So you have to convert the dates, on query, but also on storage, to some format it will understand. There are two options:
Number of seconds since some epoch, e.g. unix time, possibly fractional.
Strings.
To make comparison of strings work, the dates must be stored in the ISO 8601 format (or at least that order). ISO 8601 timestamp has format specification "%FT%T" (or on systems that don't understand %F or %T "%Y-%m-%dT%H:%M:%S"). Or just dates as "%F"/"%Y-%m-%d". You can use different separators, but the only thing that will gain you is some confusion. Also SQLite has some built-in functions to work with date in ISO 8601 format.
I believe you can define the conversion somewhere so it will then be used automatically when binding query parameters, but I don't remember where. Manually is guaranteed to work.
sqllite requires date to be in YYYY:MM:DD format. You probably should use strftime with the following parameters:
endweekd = endweekd.strftime("%Y:%m:%d")
startweekd = startweekd.strftime("%Y:%m:%d")

Categories

Resources