MDX last order date and last order value - ssas

I've googled but I cannot get the point
I've a fact table like this one
fact_order
id, id_date, amount id_supplier
1 1 100 4
2 3 200 4
where id_date is the primary key for a dimension that have
id date month
1 01/01/2011 january
2 02/01/2011 january
3
I would like to write a calculated member that give me the last date and the last amount for the same supplier.

Last date and last amount -- it's a maximum values for this supplier?
If "yes", so you can create two metrics with aggregation "max" for fields id_date and amount.
And convert max id_date to appropriate view in the following way:
CREATE MEMBER CURRENTCUBE.[Measures].[Max Date]
AS
IIF([Measures].[Max Date Key] is NULL,NULL,
STRTOMEMBER("[Date].[Calendar].[Date].&["+STR([Measures].[Max Date Key])+"]").name),
VISIBLE = 1 ;
It will works, If maximum dates in your dictionary have maximum IDs. In my opinion You should use date_id not 1,2,3..., but 20110101, 20110102, etc.
If you don't want to obtain max values - please provide more details and small example.

Related

SQL query compare value with average of similiar records

The table has 3 columns : Category, Value(int), Date
What I want the SQL query to do is check for each record belonging to a specific category, if the value lies within a specific tolerance range (say t) of the average of value over last 100 records which have the same weekday (monday, tuesday, etc) and same category as that of the concerned record.
I was able to implement this partially, as I know the Category before hand, but the weekday depends on the record which is queried. Also, currently I am just checking if the value is greater than the average, instead of which I need to check if it lies within a certain tolerance.
SELECT Value, Date,
CASE WHEN
value > (SELECT AVG(value) FROM Table WHERE Category = 'CategoryX' and Date BETWEEN current_date - 700 and current_date - 1) THEN 1
ELSE 0
END AS check_avg
FROM Table
WHERE Category = 'CategoryX'
Sample :
Category
Value
Date
CategoryX
5000
2022-06-29
CategoryX
4500
2022-06-27
CategoryX
1000
2022-06-22
CategoryY
4500
2022-06-15
CategoryX
2000
2022-06-15
CategoryX
3000
2022-06-08
Expected Result :
Value in Record with today's date : 5000.
Average of values in records with same weekday and same category : 1000 + 2000 + 3000 / 3 = 2000.
If tolerance is 50%, then allowed value should be between 1000 - 3000.
So result should be 0
Validate that in both queries you are evaluating the same category and same weekday. Then sort the values that will be used to compute the average by date, and getting only the inmediate previous 100 records. Finally, check the difference between current value and average is below the tolerance interval epsilon.
SELECT Value, Date,
CASE WHEN
ABS(value - (SELECT AVG(Value) FROM (SELECT TOP 100 Value FROM Table WHERE Category = t.Category and DATEPART(WEEKDAY, Date)=DATEPART(WEEKDAY, t.Date) AND Date <= t.Date ORDER BY Date DESC ))) < epsilon THEN 1
ELSE 0
END AS check_avg
FROM Table t
WHERE Category = 'CategoryX'

SQL to calculate daily average for a column with records of some dates are missing

I have table like below:
I have to calculate daily average count of session for each user.
First i calculated, total no of sessions for each day for every user and from that i tried to calculate average of daily session. I understand that it wont work since all users dont have sessions for every date.Some dates are missing for all users. Is there any way to calculate daily average when there is no entries for some dates
WITH daily_count AS
(
SELECT user_id, to_char(local_time,’MM/DD/YYYY’) AS Date, count(session_id) AS total_count
FROM table_name
GROUP BY device_id, to_char(local_time,’MM/DD/YYYY’)
)
SELECT user_id , AVG(total_count) AS average_session_count
FROM daily_count
GROUP BY user_id
For eg: The max date in the above given table is Feb04 and the min date is Jan31 .So the total no of days is 5 days.If we take Userid 1, it is having records only for 2 dates. So the query i wrote will calculate average for 2 days not for 5 days. How to make it to calculate average for 5 days
if for date 1,2,3 number of sessions for one user is 1,0(no sessions),5 then what output do you want in average sessions? --> 2 or 3?
You need to change your main query as follows:
SELECT USER_ID,
AVG(TOTAL_COUNT) AS AVERAGE_SESSION_COUNT -- if you want output as 3 then use this
--SUM(TOTAL_COUNT)/(MAX(DATE) - MIN(DATE) + 1) -- if you want output as 2 then use this
FROM DAILY_COUNT
GROUP BY USER_ID

SQL Find latest record only if COMPLETE field is 0

I have a table with multiple records submitted by a user. In each record is a field called COMPLETE to indicate if a record is fully completed or not.
I need a way to get the latest records of the user where COMPLETE is 0, LOCATION, DATE are the same and no additional record exist where COMPLETE is 1. In each record there are additional fields such as Type, AMOUNT, Total, etc. These can be different, even though the USER, LOCATION, and DATE are the same.
There is a SUB_DATE field and ID field that denote the day the submission was made and auto incremented ID number. Here is the table:
ID NAME LOCATION DATE COMPLETE SUB_DATE TYPE1 AMOUNT1 TYPE2 AMOUNT2 TOTAL
1 user1 loc1 2017-09-15 1 2017-09-10 Food 12.25 Hotel 65.54 77.79
2 user1 loc1 2017-09-15 0 2017-09-11 Food 12.25 NULL 0 12.25
3 user1 loc2 2017-08-13 0 2017-09-05 Flight 140 Food 5 145.00
4 user1 loc2 2017-08-13 0 2017-09-10 Flight 140 NULL 0 140
5 user1 loc3 2017-07-14 0 2017-07-15 Taxi 25 NULL 0 25
6 user1 loc3 2017-08-25 1 2017-08-26 Food 45 NULL 0 45
The results I would like is to retrieve are ID 4, because the SUB_DATE is later that ID 3. Which it has the same Name, Location, and Date information and there is no COMPLETE with a 1 value.
I would also like to retrieve ID 5, since it is the latest record for the User, Location, Date, and Complete is 0.
I would also appreciate it if you could explain your answer to help me understand what is happening in the solution.
Not sure if I fully understood but try this
SELECT *
FROM (
SELECT *,
MAX(CONVERT(INT,COMPLETE)) OVER (PARTITION BY NAME,LOCATION,DATE) AS CompleteForNameLocationAndDate,
MAX(SUB_DATE) OVER (PARTITION BY NAME, LOCATION, DATE) AS LastSubDate
FROM your_table t
) a
WHERE CompleteForNameLocationAndDate = 0 AND
SUB_DATE = LastSubDate
So what we have done here:
First, if you run just the inner query in Management Studio, you will see what that does:
The first max function will partition the data in the table by each unique Name,Location,Date set.
In the case of your data, ID 1 & 2 are the first partition, 3&4 are the second partition, 5 is the 3rd partition and 6 is the 4th partition.
So for each of these partitions it will get the max value in the complete column. Therefore any partition with a 1 as it's max value has been completed.
Note also, the convert function. This is because COMPLETE is of datatype BIT (1 or 0) and the max function does not work with that datatype. We therefore convert to INT. If your COMPLETE column is type INT, you can take the convert out.
The second max function partitions by unique Name, Location and Date again but we are getting the max_sub date this time which give us the date of the latest record for the Name,Location,Date
So we take that query and add it to a derived table which for simplicity we call a. We need to do this because SQL Server doesn't allowed windowed functions in the WHERE clause of queries. A windowed function is one that makes use of the OVER keyword as we have done. In an ideal world, SQL would let us do
SELECT *,
MAX(CONVERT(INT,COMPLETE)) OVER (PARTITION BY NAME,LOCATION,DATE) AS CompleteForNameLocationAndDate,
MAX(SUB_DATE) OVER (PARTITION BY NAME, LOCATION, DATE) AS LastSubDate
FROM your)table t
WHERE MAX(CONVERT(INT,COMPLETE)) OVER (PARTITION BY NAME,LOCATION,DATE) = 0 AND
SUB_DATE = MAX(SUB_DATE) OVER (PARTITION BY NAME, LOCATION, DATE)
But it doesn't allow it so we have to use the derived table.
So then we basically SELECT everything from our derived table Where
CompleteForNameLocationAndDate = 0
Which are Name,Location, Date partitions which do not have a record marked as complete.
Then we filter further asking for only the latest record for each partition
SUB_DATE = LastSubDate
Hope that makes sense, not sure what level of detail you need?
As a side, I would look at restructuring your tables (unless of course you have simplified to better explain this problem) as follows:
(Assuming the table in your examples is called Booking)
tblBooking
BookingID
PersonID
LocationID
Date
Complete
SubDate
tblPerson
PersonID
PersonName
tblLocation
LocationID
LocationName
tblType
TypeID
TypeName
tblBookingType
BookingTypeID
BookingID
TypeID
Amount
This way if you ever want to add Type3 or Type4 to your booking information, you don't need to alter your table layout

Get Months between two Date columns

I have a table AreaValues with columns ID, Name, Value, startDate, EndDate.
I need to view a report that select the values of every month with month name or number
Example: this is my table AreaValues:
ID Name Value StartDate EndDate
-------------------------------------------
1 Test 200 05-06-2012 07-08-2016
I need report get the value using SQL Server Reporting Services or query or any way:
month value = (200 / count of months from startdate to end date)
ID Name Value year2012 year2013 year2014 year2015 year2016
1 test 200 6,7,8,9,10,11,12 1,2,3,....12 1,2,3,....12 1,2,3,....12 1,2,3,4,5,6,7
and do that for every record in the table
Please, I need help
It Solved
I used a Loop in SQl that get all months between two dates
Then
Create report with Matrix get the months above and ID left

SQL - selecting the first record found before a given date

Say I have a table:
ID DATE
1 2/1/12
2 3/1/12
3 1/1/12
4 4/1/12
How would I go about selecting the first date found when decrementing from a given date.
Example: Find the last entry before 4/1/12, by date. Return entry at SQL ID 2.
If this was added:
ID DATE
5 3/2/12
Than the above example would return the entry at SQL ID 5.
How would I represent what I need in SQL?
Select top 1 ID, DATE
from table
where DATE < '4/1/12'
order by DATE DESC
other ideas: (in addition to Gratzy's)
select the MAX date where the date is less than the target date.
use a LAG function.