Hoping to get some help on a rather interesting formula!
Column A = Start Date
Column B = End Date
Column C = # Sales
Goal: create a calculator on the same sheet that allows me to input two dates (Start Date/End Date), and have the output be the sum of all values in Column C within that defined range (see image).
Problem: figuring out a way to have the formula recognize and sum the data in between the rows that are within the data range but not directly equal to the values that define the range (in other words, I can only figure out formulas that sum the first and last rows of the array)
Thanks in advance!! Here's the link to a sample spreadsheet with sample data: https://docs.google.com/spreadsheets/d/1d3fKGXdvVPFJNJA-TgHbH7t250GS2pQQCWvQC31T5Ow/edit#gid=0
use:
=SUMIFS(C2:C, A2:A, ">="&E3, B2:B, "<"&F3)
Another option if you want to write SQL:
=QUERY(
A:C,
"
SELECT
SUM(C)
WHERE
A >= DATE '"&TEXT(E3, "yyyy-mm-dd")&"'
AND B < DATE '"&TEXT(F3, "yyyy-mm-dd")&"'
LABEL
SUM(C) ''
"
, 1)
You can also try using FILTER in combination with sum.
I find this approach nicer since the SUMIFS has some strange shorthand.
=SUM(FILTER(C2:C14,A2:A14>=E3,B2:B14<F3))
If you use filter you might have an extra column saying the city (e.g. column D would be Dallas or Copenhagen), and then you could filter that also. In your case you would add to the filter, D2:D14="Dallas".
I put the code in your shared sheet.
Cheers Mads
Related
I made a spreasheet to follow the growth of my income. It include a script that save periodically what I've earned. Column A is DATES, Column B is how much.
I want to calculate my daily average profit.
So I went to substract yesterday to today and then make an average of all that data. But there is a problem along the way because my script is saving data many times a day (to ensure I get data, and to tack more precisely).
I would like to first calculate an average profit for each day individually (C column on screenshot)
Then calculate the variation (D column on screenshot)
Then average the variation. (E column on screenshot)
As my data are growing each day, I'm looking for a flexible way to do it. I think QUERY may be a way but I don't know how to do that. A script would work too I guess. Maybe with the FILTER formula...
What's your thoughts on that ?
Cheers,
NipthiAe.
To calculate the daily profits you shouldn't make an average of the portfolio on each time. For example, if in a single day you have
Portfolio
1
2
3
4
The average would be 2.4 but that's not the day's profits. To calculate a day's profits you need to subtract the last value of the day with the last value of the day before. In this case, if the last value was 0, the answer is 4.
Here is how I would do this.
Solution
Step 1: Find the value of the protfolio when closing the day
What we need to do is find the latest value of each day. The simplest way of doing so is to find the last entry (using the datetime) of the day. So to get the last datetime we can use (in my case added it to D2):
=query({A3:A, arrayformula(int(A3:A))}; "select max(Col1) where Col1 is not null group by Col2 label max(Col1) ''"; 0)
Let's unpack this formula:
{A3:A, arrayformula(int(A3:A))}
It's a 2 column array. The first column are the datetimes. The second column are only the dates. That relies on the fact that int(datetime) returns the number representing the day. Add arrayformula to get it for each datetime and you get the day for each one.
Then the query:
select max(Col1)
where Col1 is not null
group by Col2
order by max(Col1)
label max(Col1) ''
The trick here is to get the biggest (latest) datetime within a day. This can be achieved by selecting max(datetime) and grouping by date. Then we can add a filter for empty cells (where Col1 is not null) and order the result to ensure the correct ordering. Also remove the default label by adding label max(Col1) '' at the end.
Step 2: Get the last value
Now that we have the last datetime of the day we can use vlookup to get the value (on E3):
=arrayformula(if(D3:D<>""; vlookup(D3:D; A3:B; 2; false); ""))
As you can see it's a simple vlookup that was wrapped in an if to prevent getting an error on empty cells. arrayformula allows us to do it for each row in one formula.
Step 3: Getting the daily profit
Now that we have the latest value we only need to subtract the row with the previous one (on F3):
=arrayformula(if(E3:E100<>""; E3:E-offset(E3:E; -1; 0); ""))
offset allows us to use this formula without having to specify the number of rows. As always, arrayformula allows us to do it for all rows in a single formula and we filter empty rows.
Step 3: Total average
We can finally take the average:
=average(F3:F)
If you didn't start from 0, you should change it to start at the next value (F4) since the first value will be the accumulated until that point.
References
QUERY (Google Editors Help)
VLOOKUP (Google Editors Help)
ARRAYFORMULA (Google Editors Help)
OFFSET (Google Editors Help)
IF (Google Editors Help)
INT (Google Editors Help)
You can do it with 3 formulas:
First (query) in D2:
To get the average per day
=query({A2:B},
"Select Col1 ,count(Col1), avg(Col2) where Col1 is not null
group by Col1 Order By Col1 asc
label Col1 'Date', count(Col1) 'Days', avg(Col2) 'Average/day'")
Second in G4:
To get the differences between the averages obtained by the Query:
=arrayformula(if(isblank(E4:E6),"",filter(E4:E6,E4:E6>-1)-filter(E3:E6,E3:E6>-1)))
Third (above the query) in F1:
To get the average of the variations:
="Variation Avg: "& DOLLAR(round(AVERAGE(F3:F),2))
I have a form called FirstInLastOut which looks as the image below.
Based on Name or badge number I want to search between two dates.
I am using the following criteria on the query:
>=[Forms]![FirstInLastOut]![StartDateEntry] And <=[Forms]![FirstInLastOut]![EndDateEntry]
This is given me results that include other months as well. Please see the query report below.
So as you can see in the image the numbers of the dates are falling with the the parameter but getting other months as well.
How can I make it so it will only select the dates between the date ranges?
SELECT FistClockInRaw.Badgenumber, FistClockInRaw.name, FistClockInRaw.lastname, FistClockInRaw.MinOfCHECKTIME, FLastClockOutRaw.MaxOfCHECKTIME, [MaxOfCHECKTIME]-[MinOfCHECKTIME] AS TotalHours, FLastClockOutRaw.QDate, FistClockInRaw.MinOfQTime, FLastClockOutRaw.MaxOfQTime, RawCompleteQuery.CHECKTIME
FROM RawCompleteQuery, FLastClockOutRaw INNER JOIN FistClockInRaw ON (FLastClockOutRaw.Badgenumber = FistClockInRaw.Badgenumber) AND (FLastClockOutRaw.name = FistClockInRaw.name) AND (FLastClockOutRaw.QDate = FistClockInRaw.QDate)
WHERE (((FistClockInRaw.name)=[Forms]![FirstInLastOut]![FirstNameEntry]) AND ((RawCompleteQuery.CHECKTIME)>=[Forms]![FirstInLastOut]![StartDateEntry] And (RawCompleteQuery.CHECKTIME)<=[Forms]![FirstInLastOut]![EndDateEntry]));
is the Query
I assume that the forms fields StartDateEntry and EndDateEntry are bound to fields of type date.
I also assume that you are only interested to compare the date part of those form fields.
So try this condition instead to assure correct date interpreting:
WHERE FistClockInRaw.name=[Forms]![FirstInLastOut]![FirstNameEntry]
AND RawCompleteQuery.CHECKTIME >= Format([Forms]![FirstInLastOut]![StartDateEntry], "\#yyyy-mm-dd\#")
AND RawCompleteQuery.CHECKTIME <= Format([Forms]![FirstInLastOut]![EndDateEntry], "\#yyyy-mm-dd\#")
A remark:
Be aware that every date field/variable always contains a time part too!
So your current logic comparing EndDateEntry with <= can cause trouble, because you would only get results of the end date having time values of 00:00:00 in the field CHECKTIME.
If any record of CHECKTIME contains the requested end date and a time part bigger then 00:00:00, it is not in the result.
To avoid that, you should use < and add one day:
And RawCompleteQuery.CHECKTIME < Format([Forms]![FirstInLastOut]![EndDateEntry] + 1, "\#yyyy-mm-dd\#")
i have a table name expected expense in which i have 4 columns name Expense_title, Amount, expense_category, date and all the 4 columns have var char type. When I try to find expense between two dates it work fine for same year, e.g. 11/27/2018 and 12/27/2018, but it doesn't get any result when I try to find expense between two years, e.g. 12/27/2018 And 01/27/2019. please help
I am trying this query
SELECT *
from expected_expense
WHERE Date BETWEEN '$start_date' AND '$end_date'
As per the comments, this is because of the varchar type.
The between operator is nothing different than doing two closed inequalities for its range limits. In your example,
between 12/27/2018 And 01/27/2019
will be changed internally to
>= 12/27/2018 and <= 01/27/2019
but these are not dates, they are text. And the second one is less than the first, so nothing will be returned. It's like asking the question: which letter comes after q but before b? None.
Either change the fields to datetime, or use conversion functions in your query.
I am trying to create an RDL file and I need a tablix to appear in the following format.
This is how I want the results to look
The values that are in bold are hard coded values. This is how the output from the SELECT statement in the datasets looks
SQL Output
I don't know how to make the values that output from the database match with the hard coded values in the RDL file. The 'Day' field represents a day in the month and the 'Num' field represents the number of sales that were on the day. The above example shows that on the first day of the month, there were 100 sales made. I need the tablix to output in that specific format.
If the day isn't in the SQL output (no sales made that day), I want it to output blank and/or 0.
Any idea how this could be accomplished?
Use a CTE to create rows for each day you need and then join your results on. A starting point for you CTE could be:
;WITH nums AS
(SELECT 1 AS value
UNION ALL
SELECT value + 1 AS value
FROM nums
WHERE nums.value <= 30)
SELECT *
FROM nums
You'll probably then want to modify the total days based on the month you are viewing.
You can do this using lookups, but you would need to hard code a lookup in each cell. e.g. for day 1
=lookup(cint(1),Fields!Day.Value,Fields!Num.Value,"Dataset1")
A faster way would be to create a tablix on the dataset filtered on the first ten days:
=Switch(
Fields!DAY.Value <= 10 and Fields!DAY.Value >=1,"Include",
True,"Exclude"
)
Create a row group on days, then create a column with day and num, and columns with Fields!DAY.Value+10 and Fields!DAY.Value+20 with the following lookups:
=lookup(Fields!DAY.Value+10,Fields!DAY.Value,Fields!NUM.Value,"DataSet1")
=lookup(Fields!DAY.Value+20,Fields!DAY.Value,Fields!NUM.Value,"DataSet1")
Suppose i have a table leave_management that contains two dates columns
from & to with dates "2016-12-11" & "2016-12-18"
Now i want those output for given input...
1.
Input: From: "2016-12-7" & To: 2016-12-10
output: date difference is 0 (No overlap found)
2.
Input: From: "2016-12-16" & To: 2016-12-18
output: date difference is 2 (this range fully overlap with table data)
3.
Input: From: "2016-12-18" & To: 2016-12-20
output: date difference is 1 (this range overlap partially with table data)
here, formula of count date difference = (difference between given dates - overlap count)
I tried a query like this..
SELECT sum((DATEDIFF(from_date, to_date))
FROM `leave_management` s1
WHERE s1.from_date <='2016-12-20' AND s1.to_date >='2016-12-18'
This only give perfect output for first two inputs. But for third input it failed to give expected output. Please help me.
If I understand correctly, you want to use least() and greatest():
SELECT sum(DATEDIFF(greatest(from_date, '2016-12-18'), least(to_date, '2016-12-20'))
FROM `leave_management` s1
WHERE s1.from_date <='2016-12-20' AND s1.to_date >= '2016-12-18';
One caveat is that you might need to add/subtract one day from the constants, depending on whether the end dates count as overlaps.
You can use the peroid_diff function of mysql to determine the difference
SELECT PERIOD_DIFF(from,to) Diff_months table1;
Refer this https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_period-diff