Aggregate between start date and date before last in MDX - sql-server

Below member returns me Running Total between first and chosen date. It's possible to aggregate data up to one day/week/month before?
WITH
MEMBER [Measures].[SUM] AS
AGGREGATE(
NULL:TAIL(EXISTING [Date].[Date].[Date].Members).Item(0),
[Measures].[X]
)
Here is example (date can be a day, month, year...) :
DATE X SUM
------------
1 1 NULL
2 4 1
3 2 5
4 2 7

I think you've almost got it - to end the aggregation x number of days before you can use lag:
WITH
MEMBER [Measures].[SUM] AS
AGGREGATE(
NULL
:
TAIL(
EXISTING [Date].[Date].[Date].Members
).Item(0).lag(7) //<<<< finishes 7 days before chosen date
,[Measures].[X]
)

Related

SQL: Trying to find if gift was given year following first gift year

I'm using SSMS version 18.9.2 and I'm trying to get a list IDs who gave a gift the year following the year after their FIRST gift date. Meaning if their first gift was in 2019 and they gave a gift in 2020 then row count = 1, then the next person's first gift also was in 2019, but did NOT give a gift in 2020, then row count would remain 1 even though we have reviewed a total of two people. Hope that makes since.
Using a sample data as this, I would expect my row count to be 1; returning only ID 2
ID
Date
1
3/8/1981
1
2/11/1988
1
2/15/1995
2
2/22/1982
2
2/24/1983
2
3/15/1983
2
2/17/1984
3
2/16/1984
3
3/13/1984
3
6/13/1986
4
2/2/1983
4
3/11/1985
4
3/21/1986
This is the closest I've gotten to work. Notice the two different HAVINGs where as first works but the second fails which the second is how it needs to work:
SELECT DISTINCT
gifts1.giftid,
YEAR(gifts2.gifteffdat) AS 'MINYR',
YEAR(MIN(gifts1.gifteffdat)) AS 'MINYR+1'
FROM
gifts AS gifts1
INNER JOIN
gifts AS gifts2 ON gifts1.giftid = gifts2.giftid
AND DATEDIFF(year, gifts2.gifteffdat, gifts1.gifteffdat) = 1
GROUP BY
gifts1.giftid, gifts1.gifteffdat, gifts2.gifteffdat
-- THIS HAVING WORKS
HAVING
(YEAR(gifts2.gifteffdat) = 1982)
-- THIS HAVING DOESNT WORK
-- HAVING YEAR(gifts2.gifteffdat) = YEAR(MIN(gifts1.gifteffdat)) +1
I appreciate any help! Thank you!

get dates in range of provided start and end dates

I have records in database with start and end dates
i want to filter out all records with are in range of start and end date
i have two query that works , gives me records between two dates and the other query gives me records that are in range of start or end date
how do i combine these two linq query into single one so it works in both ways
Linq 1
schedulelist = (From c In db.Table1 Where c.StartDate.Value.Date <= objStartDate.Date And c.EndDate.Value.Date >= objStartDate.Date And
c.UserID = CInt(Session("UserID"))).ToList()
Linq 2
schedulelist = (From c In db.Table1 Where (c.StartDate.Value.Date >=
objStartDate.Date And c.StartDate.Value.Date <= objEndDate.Date) Or
(c.EndDate.Value.Date >= objStartDate.Date And c.EndDate.Value.Date <=
objEndDate.Date) And c.UserID = CInt(Session("UserID"))).ToList()
in db table have these values
StartDate EndDate
2019-10-08 07:00:00.000 2019-10-30 07:00:00.000
2019-10-15 07:00:00.000 2019-10-27 07:00:00.000
if search with ObjStartDate 15/10/2019 00:00:00 and ObjEndDate 27/10/2019 00:00:00
i get record No 2 when i run Linq 2
i get Record No 1 when i run Linq 1
what i should get is both records for any Linq 1 or Linq 2
so whats the better solution to combine both into one query or this query is all wrong ?
The simplest query to check if date range 1 intersects date range 2 is this:
... WHERE range2_end > range1_start
AND range1_end > range2_start
This checks all cases such as range 1 fully inside, fully contains, starts inside or ends inside range 2.

Get value to max date

I have a problem on on Qlikview.
I would like to get the associated value of the max date when I select and ID.
For example, if I have the following data:
id value date
1 2 1
1 4 2
1 6 3
1 5 4
When I select ID=1 I would like to get the associated value of the max date (4), which is 5
Thank you!
You can use set analysis to achieve this:
= Sum( {< date = {"$(=Max(date))"} >} value )
You can read more about set analysis on Qlik Help website

Merging Data to Run Specific Individual Analysis

I have two data sets. FIRST is a list of products and their daily prices from a supplier and SECOND is a list of start and end dates (as well as other important data for analysis). How can I tell Stata to pull the price at the beginning date and then the price at the end date from FIRST into SECOND for the given dates. Please note, if there is no exact matching date I would like it to grab the last date available. For example, if SECOND has the date 1/1/2013 and FIRST has prices on ... 12/30/2012, 12/31/2012, 1/2/2013, ... it would grab the 12/31/2012 price.
I would usually do this with Excel, but I have millions of observations, and it is not feasible.
I have put an example of FIRST and SECOND as well as what the optimal solution would give as an output POST_SECOND
FIRST
Product Price Date
1 3 1/1/2010
1 3 1/3/2010
1 4 1/4/2010
1 2 1/8/2010
2 1 1/1/2010
2 5 2/5/2010
3 7 12/26/2009
3 2 1/1/2010
3 6 4/3/2010
SECOND
Product Start Date End Date
1 1/3/2010 1/4/2010
2 1/1/2010 1/1/2010
3 12/26/2009 4/3/2010
POST_SECOND
Product Start Date End Date Price_Start Price_End
1 1/3/2010 1/4/2010 3 4
2 1/1/2010 1/1/2010 1 1
3 12/26/2009 4/3/2010 7 6
Here's a merge/keep/sort/collapse* solution that relies on using the last date. I altered your example data slightly.
/* Make Fake Data & Convert Dates to Date Format */
clear
input byte Product byte Price str12 str_date
1 3 "1/1/2010"
1 3 "1/3/2010"
1 4 "1/4/2010"
1 2 "1/8/2010"
2 1 "1/1/2010"
2 5 "2/5/2010"
3 7 "12/26/2009"
3 7 "12/28/2009"
3 2 "1/1/2010"
3 6 "4/3/2010"
4 8 "12/30/2012"
4 9 "12/31/2012"
4 10 "1/2/2013"
4 10 "1/3/2013"
end
gen Date = date(str_date,"MDY")
format Date %td
drop str_date
save "First.dta", replace
clear
input byte Product str12 str_Start_Date str12 str_End_Date
1 "1/3/2010" "1/4/2010"
2 "1/1/2010" "1/1/2010"
3 "12/27/2009" "4/3/2010"
4 "1/1/2013" "1/2/2013"
end
gen Start_Date = date(str_Start_Date,"MDY")
gen End_Date = date(str_End_Date,"MDY")
format Start_Date End_Date %td
drop str_*
save "Second.dta", replace
/* Data Transformation */
use "First.dta", clear
merge m:1 Product using "Second.dta", nogen
bys Product: egen ads = min(abs(Start_Date-Date))
bys Product: egen ade = min(abs(End_Date - Date))
keep if (ads==abs(Date - Start_Date) & Date <= Start_Date) | (ade==abs(Date - End_Date) & Date <= End_Date)
sort Product Date
collapse (first) Price_Start = Price (last) Price_End = Price, by(Product Start_Date End_Date)
list, clean noobs
*Some people are reshapers. Others are collapsers. Often both can get the job done, but I think collapse is easier in this case.
In Stata, I've never been able to get something like this to work nicely in one step (something you can do in SAS via a SQL call). In any case, I think you'd be better off creating an intermediate file from FIRST.dta and then merging that 2x on each of your StartDate and EndDate variables in SECOND.dta.
Say you have data for price adjustments from Jan 1, 2010 to Dec 31, 2013 (specified with varied intervals as you have shown above). I assume all the date variables are already in date format in FIRST.dta & SECOND.dta, and that variable names in SECOND do not have spaces in them.
tempfile prod prices
use FIRST.dta, clear
keep Product
duplicates drop
save `prod'
clear
set obs 1096
g Date=date("12-31-2009","MDY")+_n
format date %td
cross using `prod'
merge 1:1 Product Date using FIRST.dta, assert(1 3) nogen
gsort +Product +Date /*this ensures the data are sorted properly for the next step */
replace price=price[_n-1] if price==. & Product==Product[_n-1]
save `prices'
use SECOND.dta, clear
foreach i in Start End {
rename `i'Date Date
merge 1:1 Product Date using `prices', assert(2 3) keep(3) nogen
rename Price Price_`i'
rename Date `i'Date
}
This should work if I understand your data structures correctly, and it should address the issue being discussed in the comments to #Dimitriy's answer. I'm open to critiques on how to make this nicer as its something I've had to do a few times and this is how I usually go about it.

Utilizing SQL datepart to indentify consecutive periods of time

I have a stored procedure that works correctly, but don't understand the theory behind why it works. I'm indentifying a consecutive period of time by utilizing a datepart and dense rank (found solution through help elsewhere).
select
c.bom
,h.x
,h.z
,datepart(year, c.bom) * 12 + datepart(month, c.bom) -- this is returning a integer value for the year and month, allowing us to increment the number by one for each month
- dense_rank() over ( partition by h.x order by datepart(year, c.bom) * 12 + datepart(month, c.bom)) as grp -- this row does a dense rank and subtracts out the integer date and rank so that consecutive months (ie consecutive integers) are grouped as the same integer
from
#c c
inner join test.vw_info_h h
on h.effective_date <= c.bom
and (h.expiration_date is null or h.expiration_date > c.bom)
I understand in theory what is happening with the grouping functionality.
How does multiplying year * 12 + month work? Why do we multiply the year? What is happening in the backend?
The year component of a date is an integer value. Since there are 12 months in a year, multiplying the year value by 12 provides the total number of months that have passed to get to the first of that year.
Here's an example. Take the date February 11, 2012 (20120211 in CCYYMMDD format)
2012 * 12 = 24144 months from the start of time itself.
24144 + 2 months (february) = 24146.
Multiplying the year value by the number of months in a year allows you to establish month-related offsets without having to do any coding to handle the edge cases between the end of one year and the start of another. For example:
11/2011 -> 24143
12/2011 -> 24144
01/2012 -> 24145
02/2012 -> 24146

Resources