Expanding SQL query for multiple dates - sql

I have a SQL query that includes a __DATE__ macro. A Python script replaces this macro with the current date and then the statement is executed thus giving one day's worth of data.
For the first item selected, I would like to use tblLabTestResult.CollectionDate instead of __DATE__.
I would like to include the prior 7 days instead of just the current day.
The desired output would be something similar to:
Date,Result,Total
2021-08-28,Detected,5
2021-08-28,Not Detected,9
2021-08-29,Detected,23
2021-08-29,Not Detected,6
2021-08-30,Detected,88
2021-08-30,Not Detected,26
Current query:
SELECT
'__DATE__' as Date,
tblLabTestResult.Result as Result,
Count(tblLabTestResult.Result) as Total
FROM
PncRegDb.dbo.tblLabTestResult as tblLabTestResult
WHERE
tblLabTestResult.TestName like '%cov%'
AND tblLabTestResult.TestName not like '%aoe%'
AND tblLabTestResult.TestName not like '%antibody%'
AND tblLabTestResult.CollectionDate >= '__DATE__'
AND tblLabTestResult.CollectionDate <= '__DATE__ 11:59:59 PM'
GROUP BY
tblLabTestResult.Result;
How can I change my SQL query to accommodate these requirements? I am using MS SQL Server.

You can use DATEADD() function to get the date from 7 days ago and use all dates between date-7days and date. I have updated where condition in your query below:
SELECT
'__DATE__' as Date,
tblLabTestResult.Result as Result,
Count(tblLabTestResult.Result) as Total
FROM
PncRegDb.dbo.tblLabTestResult as tblLabTestResult
WHERE
tblLabTestResult.TestName like '%cov%'
AND tblLabTestResult.TestName not like '%aoe%'
AND tblLabTestResult.TestName not like '%antibody%'
AND tblLabTestResult.CollectionDate between DATEADD(day, -7, '__DATE__') and '__DATE__ 11:59:59 PM'
GROUP BY
tblLabTestResult.Result;

A few points:
Columns that are not aggregated must be in the GROUP BY
You should be passing your date as a parameter
Best to use a half-open interval to compare dates (exclusive end-point), so #endDate is the day after the one you want
Use short, meaningful aliases to make your code more readable
It doesn't make sense to group and aggregate by the same column. If Result is a non-nullable column then Count(Result) is the same as Count(*)
If you want to group by whole days (and CollectionDate has a time component) then replace ltr.CollectionDate with CAST(ltr.CollectionDate AS date) in both the SELECT and GROUP BY
SELECT
ltr.CollectionDate as Date,
ltr.Result as Result,
COUNT(*) as Total
FROM
PncRegDb.dbo.tblLabTestResult as tblLabTestResult
WHERE
ltr.TestName like '%cov%'
AND ltr.TestName not like '%aoe%'
AND ltr.TestName not like '%antibody%'
AND ltr.CollectionDate >= #startdate
AND ltr.CollectionDate < #endDate
GROUP BY
ltr.CollectionDate, ltr.Result;

Related

Is there a way to turn these multiple SQL queries into one?

I have a query that looks like this:
SELECT COUNT(*)
FROM table
WHERE date_field >= '2018-04-08'
AND date_field <= '2018-04-14'
I need to do this 26 times, for the current week and for 25 previous weeks, with each result separated by a carriage return. Is this possible with a single SQL query or do I need to put it in a loop, as I'm now doing?
Note that this is in FileMaker. I don't think that's relevant, but now you know, just in case.
Look into using "group by". Assuming that you are looking at calendar weeks, grouping by the week of the date will give you the counts per week and an extra condition can limit the overall range.
FileMaker has a WeekOfYearFiscal() function. 2nd parameter is the day of week start date.
SELECT WeekOfYearFiscal(dateField;2), COUNT(*)
FROM table
WHERE date_field >= '2018-01-01'
AND date_field <= '2018-04-14'
group by WeekOfYearFiscal(dateField;2)
See this documentation - http://www.filemaker.com/help/12/fmp/html/func_ref1.31.28.html
Give this a go. If the GROUP BY doesn't work on the function, you can nest the inner part and give an alias.

Select Query between dates not retrieving any data

I have been trying to retrieve the rows registered between two dates (since every time a person goes through a door a row is inserted). This way we get the "amount of visitors" on a monthly basis.
When querying the following:
select MOV_DATAHORA from LOG_CREDENCIAL
WHERE MOV_DATAHORA>'2017-01-01'`
a total of 5851 rows are shown. This is an example of a row:
2017-01-05 21:33:30.000
However when trying the following:
select MOV_DATAHORA from LOG_CREDENCIAL
WHERE MOV_DATAHORA>'2017-01-01'
AND MOV_DATAHORA<'2017-01-02'
0 rows are shown. I even tried the count(MOV_DATAHORA) statement but it still isn't working. I also tried with the BETWEEN statement unsuccessfully. Any ideas why?
Well... the simplest explanation based on your query predicate:
WHERE MOV_DATAHORA > '2017-01-01'
AND MOV_DATAHORA < '2017-01-02'
is that on January 1st (right after the New years) there were no visitors.
You are comparing a DateTime and a Date data types. Your table has a DateTime as you can see the 21:33:30.000 after the date, to convert and compare like types do the following.
SELECT MOV_DATAHORA FROM LOG_CREDENCIAL WHERE DATE(MOV_DATAHORA)>'2017-01-01'
AND DATE(MOV_DATAHORA)<'2017-01-02'
or using between
SELECT MOV_DATAHORA FROM LOG_CREDENCIAL WHERE DATE(MOV_DATAHORA) BETWEEN '2017-01-01'
AND '2017-01-02'

SQL: select datetime values prior to that date based on it's value

I want to select rows for a field MRD which is declared as date where it is prior for that date only.
So
(case when sum (transPoints) > 4 and MRD is that same date then 4
So if a row has a date of today, I want the case when to be triggered when the transaction points are bigger than 4 against all columns with the same date.
As you can imagine the date field will be different against many rows.
Based on what I can understand from your question, it seems that the GROUP BY clause may be what you're looking for. If your date column is in the correct format then you may have to use something like:
SELECT CAST(DateColumn as DATE)
FROM YourTable
GROUP BY CAST(DateColumn as DATE)

SQL to filter for records more than 30 days old

Suppose I have the following query:
select customer_name, origination_date
where origination_date < '01-DEC-2013';
I would like to select all customers that have an origination date older than 30 days. Is there a way in SQL (oracle, if specifics needed) to specify it in a more dynamic approach than manually entering the date so that I don't need to update the query every time I run it?
Thanks!
Sure try something like this:
select customer_name, origination_date where
origination_date >= DATEADD(day, -30, GETUTCDATE());
This basically says where the origination_date is greater or equal to 30 days from now. This works in Microsoft SQL, not sure but there is probably a similar function on Oracle.
in Oracle, when you subtract dates, by default you get the difference in days, e.g.
select * from my_table where (date_1 - date_2) > 30
should return the records whose date difference is greater than 30 days.
To make your query dynamic, you parameterize it, so instead of using hard coded date values, you use:
select * from my_table where (:date_1 - :date_2) > :threshold
If you are using oracle sql developer to run such a query, it will pop up a window for you to specify the values for your paramteres; the ones preceded with colon.

SQL How to convert date DD-MM-YYYY to MM-YYYY and retrieve most recent records?

Hi I have to retrieve from my table most recent records that match a given MM-YYYY, but the date field in the table is DD-MM-YYYY, how do I get this done?
Thank you very much
Best Regards
Ignacio.
How many of the most recent records do you need?
Could you not query for all the dates in the relevant month, order by the dates, and then only select the results you need from the top of the list.
For example:
SELECT TOP(1) *
FROM your_table
WHERE date_time_field >= '20120101'
AND date_time_field < '20120201'
ORDER BY date_time_field DESC
This would select the most recent record from January of this year.
Change the number inside the TOP() statement to change the number of results returned, or leave it off altogether and take comfort in the fact that your results are ordered.
SELECT * FROM `your`.`schemaTableNames` WHERE your_coulumn_name LIKE "%-MM-YYYY";
should give you the matching records, as you wrote that you want to retrieve.
Have you tried using DateDiff(month, date1, date2) == 0 in your where clause?
This assumes that you can convert both values to DATETIME. If you only have the year and the month, every month has day 01.
to convert a date to desire format you can use style to retrive the records date formats
The following works:
right(select convert(varchar, <date field>, 110), 7)
The full query would look someting like this:
select *
from table
where right(select convert(varchar, <date field>, 110), 7) = 'MM-YYYY'