Not Getting All Records In a Query - sql

I'm using a GoDaddy-based SQL Server 2005 to store sales from a web site. I have a datePaid column that is formatted as smalldatetime. When I query the database to display all orders for a certain date, using this query:
SELECT DISTINCT
purchase.orderID, wfRegister.firstName, wfRegister.lastname,
storeOrder.subtotal, storeOrder.handling, storeOrder.total,
storeOrder.datePaid, storeOrder.dateOrdered, storeOrder.paypalID
FROM
wfRegister
INNER JOIN
(storeOrder INNER JOIN purchase ON storeOrder.orderID = purchase.orderID) ON wfRegister.customerID = storeOrder.customerID
WHERE
storeOrder.deleted = 0
AND storeOrder.datePaid BETWEEN '03/21/2013' AND '03/21/2013'
ORDER BY
storeOrder
I only get one record returned for the 21st, which is not correct. If I change the query to storeOrder.datePaid BETWEEN '03/21/2013' AND '03/22/2013 I get 7 records returned for the 21st, which is correct, but then I also get records from the 22nd, which I don't want. Is there a way to query the datePaid field for the 21st and get all 7 records returned and not just 1? My client imports the data into Excel and does not want to have to delete the records from the 22nd to get all the records from the 21st

For date arithmetic in SQL Server using strings, I would recommend to always use the ISO-8601 standard format: YYYYMMDD - this is the only format that is independent of any regional and/or language settings.
To reliably get all orders from a given day, you should use
AND storeOrder.datePaid >= '20130321' AND storeOrder.datePaid < '20130322'
The BETWEEN seems handy - but it's inclusive, e.g. you get the data from the 22nd of March, too.
This clause here gives you all records from the 21st of March, regardless of their time - but nothing from the 22nd.

Related

Weird query result when filtering dates in SQL

I have a 40 thousand rows .csv file of football matches with dates on each game. I have formatted the dates column in 'YY-MM-DD' format with lubridate in R, so every row is like that and checked if it's in Date class, which it is.
After that I just saved the .csv file (with fwrite function in data.table) and added it to my database which is in sqlite3.
When I run this query:
-- The important part is the WHERE clause
SELECT dates, home_team, away_team, home_score, away_score, city, country FROM History_games
WHERE dates < '19300713'
To filter and get games before the 13th of July of 1930. The query runs but I get matches up to: 1930-12-07 (which is the 7th of December 1930).
If I use 19301307 (which would be wrong) the same result comes back.
I did the same filter in R with lubridate and in Python with pandas and there was no problem. My last row is 1930-07-06 (July the 6th of 1930), which is the correct date.
Could somebody tell me what is wrong with the query? I have tried it in db browser sqlite3 and datagrip and both of them throw the same result.
Thanks

Detecting Invalid Dates in Oracle 11g database (ORA-01847 )

I am querying an Oracle 11.2 instance to build a small data mart that includes extracting the date of birth and date of death of people.
Unfortunately the INSERT query (which takes its data from a SELECT) fails due to ORA-01847 (day of month must be between 1 and last day of month).
To find my bad dates I first did:
SELECT extract(day FROM SOME_DT_TM),
extract(month FROM SOME_DT_TM),
COUNT(*)
FROM PERSON
GROUP BY extract(day FROM SOME_DT_TM), extract(month FROM SOME_DT_TM)
ORDER BY COUNT(*) DESC;
It gave me 367 rows, one for each day of the year including NULL and February-29th (leap year). True for the other date column as well, so it looks like the data is fine from a SELECT perspective.
However if I set logging up on my insert
create table registry_new_dates
(some_dob date, some_death_date date);
exec dbms_errlog.create_error_log('SOME_NEW_DATES');
And then run my long insert query:
SELECT some_dob,some_death_date,ora_err_mesg$ FROM ERR$_SOME_NEW_DATES;
I get the following weird results (first 3 rows shown) which makes me think that zip codes have been somehow inserted instead of dates for the 2nd column.
31-DEC-25 35244 "ORA-01847: day of month must be between 1 and last day of month"
13-DEC-33 35244-3402 "ORA-01847: day of month must be between 1 and last day of month"
23-JUN-58 35235 "ORA-01847: day of month must be between 1 and last day of month"
My question is - how do I detect these bad rows (there are 11 apparentlyh) with an SQL statement so I can fix or remove them. Fixing them in the originating table is not an option (no write privileges). I tried using queries like this:
SELECT DECEASED_DT_TM
FROM WH_CLN_PERSON
WHERE DECEASED_DT_TM LIKE '35%'
AND rownum<3;
But it did not find the offending rows.
Not sure if you are still actively researching this (or if you got an answer already).
To find the rows with the bad data, can't you instead select the DOB and the date of death, and express the WHERE clause in terms of DOB - like so:
...WHERE some_dob = to_date('31-DEC-25')
? After you find those rows, you may want to do another query on just one or two of those rows, including a calculated column: dump(date of death). Then post that. We can learn a lot from the dump - the internal representation of the so-called "date" (which may very well be a ZIP code instead). With that in hand we may be able to figure out what's stored, and how to hunt for it.

SQL search date range in part of text field

I have a text field in a SQL database with dates that are generally like 13 Jan 1897 but could be just 1962 or Jan 2013 or ?1956 etc.
I want to be able to do a WHERE on year ranges. eg. from 1945 to 1987.
I realise that it may be difficult to cater for all formats of the data. I would be happy if it just catered for:
13 Feb 1972, and Feb 1972, and 1972
If the only date formats you are concerned about are like those above and you just want the Year it looks like you could just use the last 4 characters of the value.
In SQL Server that would be:
RIGHT(datefield,4)
Or in most languages (including SQL Server):
SUBSTRING(datefield,LEN(datefield)-3,4)
In ANSI SQL:
MID(datefield,LEN(datefield)-3,4)
Given you are using MySQL. If you want to be able to query your table with proper date comparisons, you may want to create a new field with DATETIME type and fill it with DATETIMES generated from your current field. You'd need queries like :
UPDATE _TABLE_ set NEW_DATETIME_FIELD = STR_TO_DATE(_CURRENT_FIELD_, '%Y') where CHAR_LENGTH(_CURRENT_FIELD_) = 4;
The above query would work for records with values in _CURRENT_FILED_ like '1945'. You'd need to run this query for each type of date string you got in the current field.
The new DATETIME field will allow you to properly use MySQL date functions against it.

Query to get Daywise on the month selected

I have an MS Access database table datetime column. When I select a particular month (say, July), I have to get datewise data in that month.
The output should appear in the same format as the attached image.
Every Employee who comes in on a particular date should display “P” for that day. If the Employee doesn’t come in on a particular day (like Sat or Sun), then I have to display “WO” for that day.
When an Employee has not come in (like Sat or Sun), then there is no entry in the log table for that date.
How could an Access query be written to obtain this output? I am using an MS Access 2003 database.
Edit: we have to use TRANSFORM and PIVOT, but the issue is when an employee is not available (Sat, Sun) we still need to show data in the output.
Set up a query that reads EmpID and CheckTime from the first table, and adds one additional column:
DateWise: IIf(Weekday([CheckTime])=1 Or Weekday([CheckTime])=7,"WO","P")
You will need an additional table with every date of the year in it (we'll call it YearDates). Left join that table to your query like so:
Select YD.YearDates, Q2.* from YearDates YD LEFT JOIN Query2 Q2 ON YD.YearDates = DATEVALUE(Q2.CheckTime)
The DATEVALUE will strip the time off your dates in CheckTime so they will match date against date.

Getting the range in SQL when given between

I am wondering if it's possible (without actually parsing the given string) to get the actual range (in terms of days, minutes or seconds) that is specified when you have an SQL statement like
[select 'x'
from dual
where date between to_date('20111113152049')
and to_date('20120113152049')]
I am working on a query where I'm given a string in the form of
"between to_date(A) and to_date(B)"
and would like to get that value in days to compare to a policy we let the user set so they don't enter a date range longer than say a week.
Assuming you're looking for a theoretical answer (that is: don't take this into production) this could work:
Prerequistes:
have three tables: days_seq(day_seq), month_seq(mth_seq) and year_seq(yr_seq)
days has the numbers 1...31, month 1..12, years 2011....?
Use te following query (I used access because I don't have proper RDBMS available here, keep in mind that MS-ACCESS/JET is forgiving in the use of the Dateserial function, that is, it doesn't break when you ask the dateserial for february, 30th, 2012)
SELECT Max(DateSerial(
[year_seq]![yr_seq]
,[month_seq]![mth_seq]
, [days_seq]![day_seq]))
-
Min(DateSerial(
[year_seq]![yr_seq]
,[month_seq]![mth_seq]
,[days_seq]![day_seq])) AS days
FROM days_seq, month_seq, year_seq
WHERE DateSerial(
[year_seq]![yr_seq]
,[month_seq]![mth_seq]
,[days_seq]![day_seq])
BETWEEN #2012-02-1# AND #2012-02-28#
The query basically produces a carthesian product of three tables which generates all possible days in months, months in a year for as many years as you have in the years table.
Bonus:
You could off-course generate a permanent Calendar table as X-Zero suggests.
table calendar([date])
INSERT INTO calendar
SELECT DISTINCT DateSerial(
[year_seq]![yr_seq]
,[month_seq]![mth_seq]
, [days_seq]![day_seq]))
FROM days_seq, month_seq, year_seq
You still have to pick your start year and your end year wisely. According to the Maya's an enddate of december 21st, 2012 will do.