Access DateDiff In Query - ms-access

I have a query where a previous day's balances are supposed to be subtracted from the current day's balances. Here is my SQL
SELECT [206_Src_045].[Eff Date], [103_Wire_Log].[Eff Date], [103_Wire_Log].Portfolio, [206_Src_045].Activity, [206_Src_045].[SumOfUSD Balance] AS Today_Amount, [103_Wire_Log].Balance AS Yesterday_Amount, Format([Today_Amount]-[Yesterday_Amount],"Fixed") AS Difference
FROM 206_Src_045 INNER JOIN (103_Wire_Log INNER JOIN (54_Port_Activity INNER JOIN 205_Wire_Details_Clean ON [54_Port_Activity].MetlifePortCode = [205_Wire_Details_Clean].Portfolio) ON [103_Wire_Log].Portfolio = [205_Wire_Details_Clean].Portfolio) ON [206_Src_045].Activity = [54_Port_Activity].ActivityCode
WHERE ((([206_Src_045].[Eff Date])=DMax("[Eff Date]","206_Src_045")) AND ((DateDiff('d',[206_Src_045].[Eff Date],[103_Wire_Log].[Eff Date]))="1") AND (([205_Wire_Details_Clean].Negative)=IIf([206_Src_045].[SumOfUSD Balance]-[103_Wire_Log].[Balance]<0,"Yes","No")));
((DateDiff('d',[206_Src_045].[Eff Date],[103_Wire_Log].[Eff Date]))= "1"
Changes the output from
--------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------
| 206_Src_045.Eff | 103_Wire_Log.Eff Date | Portfolio | Activity | Today_Amount | Yesterday_Amount | Difference |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 06/15/2017 | 06/13/2017 | 7TZ | 4200007025 | -10000 | 21770.83 | -31770.83 |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 06/15/2017 | 06/14/2017 | 7TZ | 4200007025 | -10000 | 1000 | -11000.00 |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
To nothing, when the second line, with dates 6/15/2017 and 6/14/2017, is the correct output. How am I using it wrong? I used it in a similar fashion in another query correctly.

Double check the order of your dates. DateDiff will return a negative number if the dates are in the reverse order. To resolve the issues, either wrap the call in Abs() like Abs(DateDiff(...)) = 1 or use DateDiff(...) In (-1, 1)
A final debugging hint: It can be worth putting a problematic expression in the select clause so that you can actually see the values that an expression is returning: SELECT DateDiff('d',[206_Src_045].[Eff Date],[103_Wire_Log].[Eff Date]) As ElapsedDays, ... This would have revealed a value of -1.

Related

Displaying date between two dates without ( IIf and Citeria)

I'm new to access and coding so please bear with me.
I want my [Exp] dates that fall between 1/12/2020 and 1/7/2021 to be shown/displayed in [Exp2] record and if it doesn't fall between the two mentioned dates then show/display nothing in Exp2 record.
Example: |
| Exp | Exp2 |
| 1/5/2020 | |
| 3/8/2020 | |
| 12/13/2020| 12.13.2020 |
see in Exp2 only 3rd record is shown/displayed while the first and second are empty.
enter image description here
enter image description here
Use a query like this:
Select
[Exp],
IIf([Exp] Between #2020-12-01# And #2021-07-01#, [Exp], Null) As Exp2
From
YourTable
or use a subquery (slower):
Select
[Exp],
(Select
First(T.Exp)
From
YourTable As T
Where
T.Exp = YourTable.Exp
And
T.Exp Between #2020-12-01# And #2021-07-01#) As Exp2
From
YourTable

How to get data between start and expiration date if date is not empty or null?

I am trying to select offers between two dates, one of start and one of expiration and in case the expiration date is empty or null it will always show the offers.
Table
+----------------+---------------------+---------------------+
| deal_title | deal_start | deal_expire |
+----------------+---------------------+---------------------+
| Example Deal | 10-24-2021 16:10:00 | 10-25-2021 16:10:00 |
| Example Deal 2 | 10-24-2021 16:10:00 | NULL |
+----------------+---------------------+---------------------+
Php Function to get the current date by timezone.
function getDateByTimeZone(){
$date = new DateTime("now", new DateTimeZone("Europe/London") );
return $date->format('m-d-Y H:i:s');
}
Mysql query:
SELECT deals.*, categories.category_title AS category_title
FROM deals
LEFT JOIN categories ON deal_category = categories.category_id
WHERE deals.deal_status = 1
AND deals.deal_featured = 1
AND deals.deal_start >= '".getDateByTimeZone()."'
AND '".getDateByTimeZone()."' < deals.deal_expire
OR deals.deal_expire IS NULL
OR deals.deal_expire = ''
GROUP BY deals.deal_id ORDER BY deals.deal_created DESC
You didn't really explain what problem you're having. Having written queries like this many times in the past, you likely need parentheses around the expiration side of your date qualifications.
WHERE deals.deal_status = 1
AND deals.deal_featured = 1
AND deals.deal_start >= '".getDateByTimeZone()."'
AND (
'".getDateByTimeZone()."' < deals.deal_expire
OR deals.deal_expire IS NULL
)
If you don't put parentheses around your OR clause, then operator precedence will cause the whole WHERE clause to be true whenever the expire date is NULL and that's not what you want. You want a compounded OR clause here.
I don't think you need to compare against empty string either, just assuming you put that in there trying to figure things out so I left it out in my sample code.
Also I'm not familiar with PHP string interpolation enough to know if there's an issue with the way you're interpolating the result of the 'getDateByTimeZone' function into that query. It looks funky to me based on past experience with PHP, but I'm ignoring that part of it under the assumption that there's something wrapping this code which resolves it correctly.
The best would be to have MySQL datetimes from the start in your database
But you can do all in MySQL.
STR_TO_DATE will cost time every time it runs
When you put around all expire dates a () it will give back a true if youe of them is true
CREATE TABLE deals (
deal_id int,
deal_status int,
deal_featured int,
deal_category int,
`deal_title` VARCHAR(14),
`deal_start` VARCHAR(19),
`deal_expire` VARCHAR(19)
,deal_created DATEtime
);
INSERT INTO deals
(deal_id,deal_status,deal_featured,deal_category,`deal_title`, `deal_start`, `deal_expire`,deal_created)
VALUES
(1,1,1,1,'Example Deal', '10-24-2021 16:10:00', '10-25-2021 16:10:00',NOW()),
(2,1,1,1,'Example Deal 2', '10-24-2021 16:10:00', NULL,NOW());
CREATE TABLE categories (category_id int,category_title varchar(20) )
INSERT INTO categories VALUES(1,'test')
SELECT
deals.deal_id, MIN(`deal_title`), MIN(`deal_start`), MIN(`deal_expire`),MIN(deals.deal_created) as deal_created , MIN(categories.category_title)
FROM
deals
LEFT JOIN
categories ON deal_category = categories.category_id
WHERE
deals.deal_status = 1
AND deals.deal_featured = 1
AND STR_TO_DATE(deals.deal_start, "%m-%d-%Y %H:%i:%s") >= NOW() - INTERVAL 1 DAY
AND (NOW() < STR_TO_DATE(deals.deal_expire, "%m-%d-%Y %H:%i:%s")
OR deals.deal_expire IS NULL
OR deals.deal_expire = '')
GROUP BY deals.deal_id
ORDER BY deal_created DESC
deal_id | MIN(`deal_title`) | MIN(`deal_start`) | MIN(`deal_expire`) | deal_created | MIN(categories.category_title)
------: | :---------------- | :------------------ | :------------------ | :------------------ | :-----------------------------
1 | Example Deal | 10-24-2021 16:10:00 | 10-25-2021 16:10:00 | 2021-10-24 22:42:34 | test
2 | Example Deal 2 | 10-24-2021 16:10:00 | null | 2021-10-24 22:42:34 | test
db<>fiddle here

Using mySQL variables in subqueries

I am trying to use user defined variables to limit the results of a subquery, in order to get the difference between two timestamps in some analytics data. The code I am working with is as follows:
SELECT #visitID := `s`.`visit_id` AS `visit_id`, # Get the visit ID and assign to a variable
#dt := `s`.`dt` AS `visit`, # Get the timestamp of the visit and assign to a variable
`tmp`.`dt` AS `next-visit` # Get the 'next visit' timestamp which should be returned by the subquery
FROM `wp_slim_stats` AS `s` # From the main table...
LEFT JOIN (SELECT `s`.`visit_id`, # Start the subquery
MIN(`s`.`dt`) as `dt` # Get the lowest timestamp returned
FROM `wp_slim_stats` AS `s` # ...from the same table
WHERE `s`.`visit_id` = #visitID # Visit ID should be the same as the row the main query is working on
AND `s`.`dt` > #dt # Timestamp should be HIGHER than the row we are working on
LIMIT 0, 1) as `tmp` ON `tmp`.`visit_id` = `s`.`visit_id` # Join on visit_id
WHERE `s`.`resource` LIKE 'foo%' # Limit all results to the page we are looking for
The intention is to get an individual pageview and record its visit ID and the timestamp. The subquery should then return the next record from the database with the same visit ID. I can then subtract one from the other to get the seconds spent on a page.
The problem I am running into is that the subquery seems to be re-evaluating for each row returned, and not populating the next-visit column until the end. This means that all the rows returned are matched against the subquery's results for the final row, thus all next-visit columns are null apart from the final row.
The results I am looking for would be something like:
_________________________________________________
| visit_id | visit | next-visit|
|--------------|---------------|----------------|
| 1 | 123456789 | 123457890 |
|--------------|---------------|----------------|
| 4 | 234567890 | 234567891 |
|--------------|---------------|----------------|
| 6 | 345678901 | 345678902 |
|--------------|---------------|----------------|
| 8 | 456789012 | 456789013 |
|______________|_______________|________________|
But I am getting
_________________________________________________
| visit_id | visit | next-visit|
|--------------|---------------|----------------|
| 1 | 123456789 | NULL |
|--------------|---------------|----------------|
| 4 | 234567890 | NULL |
|--------------|---------------|----------------|
| 6 | 345678901 | NULL |
|--------------|---------------|----------------|
| 8 | 456789012 | 456789013 |
|______________|_______________|________________|
I am still fairly new to using variables in mySQL, particularly when assigning them dynamically. As I mentioned, I think I am messing up the order of operations somewhere, which is causing the subquery to re-populate each row at the end.
Ideally I need to be able to do this in pure mySQL due to restrictions that from the client, so no PHP unfortunately. Is it possible to do what I am trying to do?
Thank you!
You don't need variables here at all.
SELECT `s`.`visit_id` AS `visit_id`,
`s`.`dt` AS `visit`,
(SELECT MIN(dt) FROM `wp_slim_stats` ws WHERE ws.visit_id = s.visit_id AND ws.dt > s.dt)
FROM `wp_slim_stats` AS `s`
WHERE `s`.`resource` LIKE 'foo%'
And to answer why your solution doesn't work, have a look at the order of operations in a sql query:
FROM clause
WHERE clause
GROUP BY clause
HAVING clause
SELECT clause
ORDER BY clause
Here's the query you would need to run.
select visits.visitid as vId, temp.time as tTime, visits.time as vTime
from visits inner join (select min(id) as firstId, visitid, time from
visits v1 group by visitid)temp on visits.visitid = temp.visitid where
id > temp.firstid group by visits.visitid;
See this SQL fiddle

How can I get the difference between the individual maximum values of different days?

I am new in MySQL, I am trying to find:
The difference between a given day's maximum value occurred and the previous day's maximum value.
I was able to get the maximum values for dates via:
select max(`bundle_count`), `Production_date`
from `table`
group by `Production_date`
But I don't know how to use SQL to calculate the differences between maximums for two given dates.
am expecting output like this
Please help me.
Update 1: Here is a fiddle, http://sqlfiddle.com/#!2/818ad/2, that I used for testing.
Update 2: Here is a fiddle, http://sqlfiddle.com/#!2/3f78d/10 that I used for further refining/fixing, based on Sandy's comments.
Update 3: For some reason the case where there is no previous day was not being dealt with correctly. I thought it was. However, I've updated to make sure that works (a bit cumbersome--but it appears to be right. Last fiddle: http://sqlfiddle.com/#!2/3f78d/45
I think #Grijesh conceptually got you the main thing you needed via the self-join of the input data (so make sure you vote up his answer!). I've cleaned up his query a bit on syntax (building off of his query!):
SELECT
DATE(t1.`Production_date`) as theDate,
MAX( t1.`bundle_count` ) AS 'max(bundle_count)',
MAX( t1.`bundle_count` ) -
IF(
EXISTS
(
SELECT date(t2.production_date)
FROM input_example t2
WHERE t2.machine_no = 1 AND
date_sub(date(t1.production_date), interval 1 day) = date(t2.production_date)
),
(
SELECT MAX(t3.bundle_count)
FROM input_example t3
WHERE t3.machine_no = 1 AND
date_sub(date(t1.production_date), interval 1 day) = date(t3.production_date)
GROUP BY DATE(t3.production_date)
), 0
)
AS Total_Bundles_Used
FROM `input_example` t1
WHERE t1.machine_no = 1
GROUP BY DATE( t1.`production_date` )
Note 1: I think #Grijesh and I were cleaning up the query syntax issues at the same time. It's encouraging that we ended up with very similar versions after we were both doing cleanup. My version differs in using IFNULL() for when there is no preceding data. I also ended up with a DATE_SUB, and I made sure to reduce various dates to mere dates without time component, via DATE()
Note 2: I originally had not fully understood your source tables, so I thought I needed to implement a running count in the query. But upon better inspection, it's clear that your source data already has a running count, so I took that stuff back out.
I am not sure but you need something like this, Hope it will be helpful to you upto some extend:
Try this:
SELECT t1.`Production_date` ,
MAX(t1.`bundle_count`) - MAX(t2.`bundle_count`) ,
COUNT(t1.`bundle_count`)
FROM `table_name` AS t1
INNER JOIN `table_name` AS t2
ON ABS(DATEDIFF(t1.`Production_date` , t2.`Production_date`)) = 1
GROUP BY t1.`Production_date`
EDIT
I create a table name = 'table_name', as below,
mysql> SELECT * FROM `table_name`;
+---------------------+--------------+
| Production_date | bundle_count |
+---------------------+--------------+
| 2004-12-01 20:37:22 | 1 |
| 2004-12-01 20:37:22 | 2 |
| 2004-12-01 20:37:22 | 3 |
| 2004-12-02 20:37:22 | 2 |
| 2004-12-02 20:37:22 | 5 |
| 2004-12-02 20:37:22 | 7 |
| 2004-12-03 20:37:22 | 6 |
| 2004-12-03 20:37:22 | 7 |
| 2004-12-03 20:37:22 | 2 |
| 2004-12-04 20:37:22 | 1 |
| 2004-12-04 20:37:22 | 9 |
+---------------------+--------------+
11 rows in set (0.00 sec)
My query: to find difference in bundle_count between two consecutive dates:
SELECT t1.`Production_date` ,
MAX(t2.`bundle_count`) - MAX(t1.`bundle_count`) ,
COUNT(t1.`bundle_count`)
FROM `table_name` AS t1
INNER JOIN `table_name` AS t2
ON ABS(DATEDIFF(t1.`Production_date` , t2.`Production_date`)) = 1
GROUP BY t1.Production_date;
its output:
+---------------------+-------------------------------------------------+--------------------------+
| Production_date | MAX(t2.`bundle_count`) - MAX(t1.`bundle_count`) | COUNT(t1.`bundle_count`) |
+---------------------+-------------------------------------------------+--------------------------+
| 2004-12-01 20:37:22 | 4 | 9 |
| 2004-12-02 20:37:22 | 0 | 18 |
| 2004-12-03 20:37:22 | 2 | 15 |
| 2004-12-04 20:37:22 | -2 | 6 |
+---------------------+-------------------------------------------------+--------------------------+
4 rows in set (0.00 sec)
This is PostgreSQL syntax (sorry; it's what I'm familiar with) but should fundamentally work in either database. Note this doesn't exactly run in PostgreSQL either because group is not a valid table name (it's a reserved keyword). The approach is a self-join as others have mentioned but I've used a view to handle the max-by-day and the difference as separate steps.
create view max_by_day as
select
date_trunc('day', production_date) as production_date,
max(bundle_count) as bundle_count
from
group
group by
date_trunc('day', production_date);
select
today.production_date as production_date,
today.bundle_count,
today.bundle_count - coalesce(yesterday.bundle_count, 0)
from
max_by_day as today
left join max_by_day yesterday on (yesterday.production_date = today.production_date - '1 day'::interval)
order by
production_date;
PostgreSQL also has a construct called window functions which is useful for this and a bit easier to understand. Just had to stick in a bit of advocacy for a superior database. :-P
select
date_trunc('day', production_date),
max(bundle_count),
max(bundle_count) - lag(max(bundle_count), 1, 0)
over
(order by date_trunc('day', production_date))
from
group
group by
date_trunc('day', production_date);
These two approaches differ in how they handle missing days in the data - the first will treat it as a 0, the second will use the previous day which is present. There wasn't a case like this in your sample so I don't know if this is something you care about.

mysql query logic

I have an sql query which shows the delivery details of a vehicle. ( it uses greatest to fetch max value from a range of colums for each vehicle stop)
SELECT deliveryid AS deliverynumber, loadid1 AS loadnumberdate,
haulieraccepted AS haulier,
greatest(drop1arrivedatetime, drop2arrivedatetime, drop3arrivedatetime,
drop4arrivedatetime, drop5arrivedatetime) AS planneddate,
date(greatest(ActualDrop1Arrive, ActualDrop2Arrive, ActualDrop3Arrive,
ActualDrop4Arrive, ActualDrop5Arrive )) AS actualenddate,
mitigation
FROM deliverydetails
WHERE deliveryid=44
the output is
deliverynumber | loadnumberdate | haulier | planneddate | actualenddate | mitigation
44 | 484487 | stols transport | 2011-11-26 15:50:00 | 2011-11-26 | customerdelay
How can I add to the mysql query to compare columns 'planneddate' and 'actualenddate'? if the dates are the same then set the query field to 'ontime' else if actualenddate>planneddate then 'deliverylate'. So ideally I want the following output:
deliverynumber | loadnumberdate | haulier | planneddate | actualenddate | mitigation | Status
44 | 484487 | stols transport | 2011-11-26 15:50:00 | 2011-11-26 | customerdelay | ontime.
Thanks for the assistance.
You can use a CASE statement or IF function. Perhaps something like:
SELECT ...., IF(actualenddate>planneddate,'deliverylate','ontime') AS status FROM ....
use mysql if condition and date conversion function to check and display according to....
You can wrap your original query as a subquery. This will rename the columns. Then, use a case ... then clause to add the column.
Assuming your original query works just fine, it would look like this:
select
*,
case when (... some comparison on 'planneddate' and 'actualenddate' ...)
then <true output>
else <false output> end
from
(<your original query>) as myalias;
The trick is that the columns from the subquery are renamed, allowing you to use their new names (planneddate and actualenddate).