approximate Vlookup function in MS Access? - ms-access

In Access I have a table, where I enter the times I began and finished work for each day. Logically, these two numbers allow you to calculate how long you worked.
In another Table I have currently four records, defining how long the lunch break has to be on a specific day, based on how long I worked that day, something like this
Minimum work time; Minimum break
0:00; 0:00
5:31; 0:15
7:01; 0:30
9:01; 1:00
In Excel I can use the Vlookup, set to work with approximate times. For example, if one day the duration was 7:42, the Vlookup would return "0:30", going to the closest lower value, 7:01, and returning 0:30.
Is there a function in the formula editor in the query window of Access to solve this problem or does Access just lack this possibility? I'm just very curious about that.

Use a subquery to look up the break time:
SELECT
TableWork.Id,
TableWork.BeginTime,
TableWork.FinishTime,
CDate(FinishTime - BeginTime) AS WorkTime,
(Select Top 1
[Minimum break]
From
TableBreak
Where
[Minimum work time] <= ([FinishTime] - [BeginTime])
Order By
[Minimum work time] Desc) AS BreakTime,
CDate([WorkTime] - [BreakTime]) AS NetTime
FROM
TableWork
ORDER BY
TableWork.Id;

If your table field data type is Date/Time then try below query.
SELECT TOP 1 format(tblST.MinBrk,"hh:mm") as [Minimum Break]
FROM tblST
WHERE (((tblST.[MinWT])<=TimeSerial(7,42,0)))
ORDER BY tblST.MinWT DESC;
If data type is Number then try below-
SELECT TOP 1 tblST2.MinBrk as [Minimum Break]
FROM tblST2
WHERE (((tblST2.[MinWT])<=7.42))
ORDER BY tblST2.MinWT DESC;

A nested query can return break time:
SELECT tblWork.WorkTime,
Format((SELECT Max(MinimumBreak) FROM tblBreaks
WHERE MinimumWorkTime<=tblWork.WorkTime), "Short Time") AS BreakTime
FROM tblWork;
or
SELECT tblWork.WorkTime,
Format((SELECT TOP 1 MinimumBreak FROM tblBreaks
WHERE MinimumWorkTime<=tblWork.WorkTime
ORDER BY MinimumBreak DESC), "Short Time") AS BreakTime
FROM tblWork;
However, both result in a non-editable dataset so this is okay for a report but not for data entry form. Use domain aggregate function expression in textbox.
DMax("MinimumBreak", "tblBreaks", "MinimumWorkTime<=#" & Me.WorkTime & "#")

Related

Return rows for next month, MYSQL

I have a mysql table which stores users' availability, stored in 'start' and 'end' columns as date fields.
I have a form where other users can search through the 'availabilty' with various periods like, today, tomorrow and next week . I'm trying to figure out how to construct the query to get all the rows for users who are available 'next month'.
The 'start' values maybe from today and the 'end' value might might be three months away but if next month falls between 'start' and 'end' then I would want that row returned.
The nearest I can get is with the query below but that just returns rows where 'start' falls within next month. Many thanks,
sql= "SELECT * FROM mytable WHERE start BETWEEN DATE_SUB(LAST_DAY(DATE_ADD(NOW(), INTERVAL 1 MONTH)),INTERVAL DAY(LAST_DAY(DATE_ADD(NOW(), INTERVAL 1 MONTH)))-1 DAY) AND LAST_DAY(DATE_ADD(NOW(), INTERVAL 1 MONTH))";
As you are interested in anything that happens in the full month following the current date you could try something like this:
SELECT * FROM mytable WHERE
FLOOR(start/100000000)<=FLOOR(NOW()/100000000)+1 AND
FLOOR( end/100000000)>=FLOOR(NOW()/100000000)+1
This query make use of the fact that datetime values are stored in MySql internally as a number like
SELECT now()+0
--> 20150906130640
where the digits 09 refer to the current month. FLOOR(NOW()/100000000) filters out the first digits of the number (in this case:201509). The WHERE conditions now simply test whether the start date is anywhere before the end of the next month and the end date is at least in or after the period of the next month.
(In my version I purposely left out the condition that start needs to be "after today", since a period that has started earlier seems in my eyes still applicable for your described purpose. If, however, you wanted that condition included too you could simply add an AND start > now() at the end of your WHERE clause.)
Edit
As your SQLfiddle is set-up with a date instead of a (as I was assuming) datetime column your dates will be represented differently in mumeric format like 20150907 and a simple division by 100 will now get you the desired month-number for comparison (201509):
SELECT * FROM mytable WHERE
FLOOR(start/100)<=FLOOR(NOW()/100000000)+1 AND
FLOOR( end/100)>=FLOOR(NOW()/100000000)+1
The number returned by NOW() is still a 14-digit figure and needs to be divided by 100000000. See your updated fiddle here: SQLfiddle
I also added another record ('Charlie') which does not fulfill your requirements.
Update
To better accommodate change-of-year scenarios I updated my SqlFiddle. The where clause is now based on 12*YEAR(..)+MONTH(..) type functions.

mysql get data from a specific week [duplicate]

I am having a table as follows in MYSQL:
proj_id|hoursWorked|Date.
The date field is of type Date; I want to retrieve all the entries from a table depending on a given week number for the project in my java based web application. Please help me to achieve this.
I am unable to write a single query that will allow me to do so.
Do not use something like WHERE WEEK(column)=something - this is a performance killer: It will calculate the week number on all rows, even if they don't match. In addition to that it will make it impossible to use an index ont this column.
Instead calculate an absolute begin and end date or point in time, depending on your data type, then use BETWEEN. This will do no calculations on non-matching rows and allow the use of an index.
Rule of thumb: If you have the choice between a calculation on a constant and on a field, use the former.
use MySQL WEEK() function.
SELECT WEEK(dateColumn)
FROM...
WHERE WEEK(dateColumn) = 1
WEEK()
from MySQL Docs
This function returns the week number for date. The two-argument form
of WEEK() enables you to specify whether the week starts on Sunday or
Monday and whether the return value should be in the range from 0 to
53 or from 1 to 53.
Use WEEK
select * from your_table
where week(`Date`) = week('2012-12-01')
If you want to get only records from the current week you can do
select * from your_table
where week(`Date`) = week(curdate())

Calculating time difference between activity timestamps in a query

I'm reasonably new to Access and having trouble solving what should be (I hope) a simple problem - think I may be looking at it through Excel goggles.
I have a table named importedData into which I (not so surprisingly) import a log file each day. This log file is from a simple data-logging application on some mining equipment, and essentially it saves a timestamp and status for the point at which the current activity changes to a new activity.
A sample of the data looks like this:
This information is then filtered using a query to define the range I want to see information for, say from 29/11/2013 06:00:00 AM until 29/11/2013 06:00:00 PM
Now the object of this is to take a status entry's timestamp and get the time difference between it and the record on the subsequent row of the query results. As the equipment works for a 12hr shift, I should then be able to build a picture of how much time the equipment spent doing each activity during that shift.
In the above example, the equipment was in status "START_SHIFT" for 00:01:00, in status "DELAY_WAIT_PIT" for 06:08:26 and so-on. I would then build a unique list of the status entries for the period selected, and sum the total time for each status to get my shift summary.
You can use a correlated subquery to fetch the next timestamp for each row.
SELECT
i.status,
i.timestamp,
(
SELECT Min([timestamp])
FROM importedData
WHERE [timestamp] > i.timestamp
) AS next_timestamp
FROM importedData AS i
WHERE i.timestamp BETWEEN #2013-11-29 06:00:00#
AND #2013-11-29 18:00:00#;
Then you can use that query as a subquery in another query where you compute the duration between timestamp and next_timestamp. And then use that entire new query as a subquery in a third where you GROUP BY status and compute the total duration for each status.
Here's my version which I tested in Access 2007 ...
SELECT
sub2.status,
Format(Sum(Nz(sub2.duration,0)), 'hh:nn:ss') AS SumOfduration
FROM
(
SELECT
sub1.status,
(sub1.next_timestamp - sub1.timestamp) AS duration
FROM
(
SELECT
i.status,
i.timestamp,
(
SELECT Min([timestamp])
FROM importedData
WHERE [timestamp] > i.timestamp
) AS next_timestamp
FROM importedData AS i
WHERE i.timestamp BETWEEN #2013-11-29 06:00:00#
AND #2013-11-29 18:00:00#
) AS sub1
) AS sub2
GROUP BY sub2.status;
If you run into trouble or need to modify it, break out the innermost subquery, sub1, and test that by itself. Then do the same for sub2. I suspect you will want to change the WHERE clause to use parameters instead of hard-coded times.
Note the query Format expression would not be appropriate if your durations exceed 24 hours. Here is an Immediate window session which illustrates the problem ...
' duration greater than one day:
? #2013-11-30 02:00# - #2013-11-29 01:00#
1.04166666667152
' this Format() makes the 25 hr. duration appear as 1 hr.:
? Format(#2013-11-30 02:00# - #2013-11-29 01:00#, "hh:nn:ss")
01:00:00
However, if you're dealing exclusively with data from 12 hr. shifts, this should not be a problem. Keep it in mind in case you ever need to analyze data which spans more than 24 hrs.
If subqueries are unfamiliar, see Allen Browne's page: Subquery basics. He discusses correlated subqueries in the section titled Get the value in another record.

Grouping Unix Timestamp by Day Producing Unevenly Spaced Groups

I'm using a MySQL query to pull a range of datetimes as a Unix Timestamp (because I'll be converting them to Javascript time). I'm grouping by 'FROM_UNIXTIME' as below:
SELECT
UNIX_TIMESTAMP(DateAndTime) as x,
Sum(If(Pass='Pass',1,0)) AS y,
Sum(If(Pass='Fail',1,0)) AS z,
Sum(If(Pass='Fail',1,0))/(Sum(If(Pass='Pass',1,0))+Sum(If(Pass='Fail',1,0))) AS a,
cases.primaryApp
FROM casehistory, cases
WHERE DATE_SUB(CURDATE(),INTERVAL 80 DAY) <= DateAndTime
AND cases.caseNumber = casehistory.caseNumber
AND cases.primaryApp = 'Promo'
GROUP BY FROM_UNIXTIME(x, '%Y-%m-%d')
While I'd expected my timestamps to be returnd evenly spaced (that is, same amount of time between each day/group), I get the following series:
1300488140, 1300501520,
1300625099, 1300699980
All the other data from the query is correct, but because the spacing of the timestamps is irregular, a bar chart based on these stamps looks pretty awful. Perhaps I'm doing something wrong in the way I apply the grouping?
Thank you for the reply. My query 'made sense' in that it produced that could be plotted (the grouping was done on the x alias for the dateandtime value), but the problem was that pulling a Unix timestamp from the database and grouping by day returned a series of timestamps that did not have equal distance between them.
I solved this by pulling only the day (without the time) from the datetime MySQL field, then - in PHP - concatenating an empty time to the date, converting the resulting string to a time, then multiplying the whole shebang by 1000 to return the Javascript time I needed for the charting, like this:
x = x . ' 00:00:00';
x = strtotime(x) * 1000;
The answer put me on the right track; I'll accept it. My chart looks perfect now.
Question is very confused.
Your SQL statement makes no sense - you are grouping by entities not found in the select statement. And a bar chart plots an ordered set of values - so if there's something funny with the spacing then its not really a bar chart.
But I think the answer you are looking for is:
SELECT DATE_FORMAT(dateandtime, '%Y-%m-%d') as ondate
, SUM(IF(Pass='Pass',1,0)) AS passed
, SUM(IF(Pass='Fail',1,0)) AS failed
, SUM(IF(Pass='Fail',1,0))
/(SUM(IF(pass='Pass',1,0))+SUM(IF(Pass='Fail',1,0))) AS fail_pct
, cases.primaryapp
FROM casehistory, cases
WHERE DATE_SUB(CURDATE(),INTERVAL 80 DAY) <= dateandtime
AND cases.casenumber = casehistory.casenumber
AND cases.primaryapp = 'Promo'
GROUP BY DATE_FORMAT(dateandtime, '%Y-%m-%d')
ORDER BY 1;
And if you need Unix timestamps, wrap the above in....
SELECT UNIX_TIMESTAMP(STR_TO_DATE(CONCAT(ilv.ondate, ' 00:00:00'))) AS tstamp
, passed
, failed
, fail_pct
, primaryapp
FROM (
...
) AS ilv
Note that you'll still get anomolies around DST switches.
C.

Query by month from date field

I have a set of Access d/b's grouped already by year. within a given year, I have a field caleld REPORTDATE which is a standard mm/dd/yyyy field. However, I need to produce queries that return data by the month. For example, I just want to see records for Jan, recs for Feb, Recs for March, etc., so that I can sum them and work wwith thm.
Do I use an expression in the query design view Criteria field?
Thanks in advance.
I just want to see records for Jan, recs for Feb, Recs for March, etc., so that I can sum them and work wwith thm.
You can do all of that in one sql statement:
select month(reportdate), sum( the column you wish to sum )
from tablename
group by month(reportdate);
BUT WAIT THERE'S MORE!
Further say that there are several salepersons selling stuff, and you wish to show each salesperson's sales by month
select month(reportdate), salesperson, sum( the column you wish to sum )
from tablename
group by month(reportdate), salesperson;
That shows the sum per month per salesperson.
You know the Germans always make good stuff!
What it you wanted to see the same sums, but rtaher than comparing salespeople against each other in each month, you wanted to compare, for each salesperson, how they did from one month to another?
Just reverse the order of the group by:
select month(reportdate), saleperson, sum( the column you wish to sum )
from tablename
group by salesperson, month(reportdate);
Tacos, Fettuccini, Linguini, Martini, Bikini, you're gonna love my nuts!
The power of SQL! As seen on TV! Order now!
"select month(reportdate), sum( the column you wish to sum )from tablenamegroup by month(reportdate);" THIS IS VERY HELPFUL, THANK YOU. AND YOU ARE HILARIOUS. HOWEVER, can you clarify for me where the heck this code goes?! In the expresison Builder or what? Thank you SO much. – rick (19 mins ago)
In Access, I think from the graphical Query Builder thing's menu, select edit|SQL, and just type. And never go back to graphical!
You're a hard-charging forward-thinking entrepreneurially-minded man on the move! This is not your father's Oldsmobile! You wouldn't use an on-screen keyboard to type a document, dragging and dropping letters on the page, would you?! So why do that to build a SQL Query? Get into SQL! AS SEEN ON TV! All the cool kids and hep cats are doin' it! Order NOW!
You can use format, for example:
Format([REPORTDATE],"mmm yy")
Or Month:
SELECT * FROM Table WHERE Month([REPORTDATE]) = 10
An outline of query that may suit, paste this into the SQL view of
the query design window, changing table to the name of your table:
SELECT Format([REPORTDATE],"yyyy mm"), Count([ReportDate])
FROM Table
GROUP BY Format([REPORTDATE],"yyyy mm")
I wouldn't do this in the report's recordsource. I'd make the recordsource a regular SELECT statement and use the report's sorting/grouping. If you group on a date field (one that is really date type), you get the choice to GROUP ON:
Each Value (default)
Year
Qtr
Month
Week
Day
Hour
Minute
I think this is faster than a GROUP BY on a function, but someone who was interested should actually try it.
Certainly if your SELECT with GROUP BY has no WHERE clause, it's going to be a lot more efficient if you run the report with filtered values.