Tableau Creating a Timeline on only two dates - timeline

I'm working on a visualization of data which represents office markets.
Therefore I'm focussing on object level instead of regional, national or global market levels. Therefore I have to treat my data differently than what is regular.
Let me provide a simple dummy by text.
I have a building A {PropertyName} which has 3 tenants {CompanyName}, tenant A, B and C. Both tenant A and B have been in the building since it has been constructed {ConstructionDate}.
Tenant C has been in the building somewhat later (6 months later).
The building is built in 2011, and all tenants are still in the building. I want to calculate the following things. I know the building has a Size {PropertySize} of 5000 m2. The lease of tenant A is 2000 m2, tenant B also has 2000 m2 and tenant C has 1000 m2.
The problem I face at the moment is that I only have the initial starting date of the lease {StartDateLease} and if applicable, an end date of the lease {EndDateLease}.
I want to add Pages in Tableau which you can scroll through (by month or quarter) and that the leases are showed whenever they (the tenants) are in the building (i.e. leasing it) and whenever the end date of the lease has been reached (or if they are not yet in the building, as tenant C is) they are not present in the building and the {PropertySize} - SUM({LeaseSize}) is calculated {PropertyVacancy}.
Preferrable I would like to add this in a stacked bar chart as well to be showed. I hope this is clear for now.
Summary of Data
{PropertyName} {CompanyName} {StartDateLease} {EndDateLease} {LeaseSize} {PropertySize} {PropertyVacancy}
Building A Tenant A 01-01-2011 01-01-2016 2000 5000 [CalculatedValue]
And so on.
Could anybody help me out based on this maybe very vague explanation?
Thanks in advance!

There are lots of business questions you could answer with your data, but I will try to stick to the question you asked. If you want to look at each quarter or month using Tableau's Page shelf, you're going to have to manipulate your data. You need a row for every Property, Tenant, and Month of the calendar in which you are concerned. This means you'll be making lots more rows. Here's the beginning of what your data needs to look like for 1/1/2011 thru 4/1/2012:
PropertyName Occupied by Month LeaseSpace
Building A Tenant A 1/1/2011 2000
Building A Tenant A 2/1/2011 2000
Building A Tenant A 3/1/2011 2000
Building A Tenant A 4/1/2011 2000
Building A Tenant A 5/1/2011 2000
Building A Tenant A 6/1/2011 2000
Building A Tenant A 7/1/2011 2000
Building A Tenant A 8/1/2011 2000
Building A Tenant A 9/1/2011 2000
Building A Tenant A 10/1/2011 2000
Building A Tenant A 11/1/2011 2000
Building A Tenant A 12/1/2011 2000
Building A Tenant A 1/1/2012 2000
Building A Tenant A 2/1/2012 2000
Building A Tenant A 3/1/2012 2000
Building A Tenant A 4/1/2012 2000
Building A Tenant B 1/1/2011 2000
Building A Tenant B 2/1/2011 2000
Building A Tenant B 3/1/2011 2000
Building A Tenant B 4/1/2011 2000
Building A Tenant B 5/1/2011 2000
Building A Tenant B 6/1/2011 2000
Building A Tenant B 7/1/2011 2000
Building A Tenant B 8/1/2011 2000
Building A Tenant B 9/1/2011 2000
Building A Tenant B 10/1/2011 2000
Building A Tenant B 11/1/2011 2000
Building A Tenant B 12/1/2011 2000
Building A Tenant B 1/1/2012 2000
Building A Tenant B 2/1/2012 2000
Building A Tenant B 3/1/2012 2000
Building A Tenant B 4/1/2012 2000
Building A NULL 1/1/2011 1000
Building A NULL 2/1/2011 1000
Building A NULL 3/1/2011 1000
Building A NULL 4/1/2011 1000
Building A NULL 5/1/2011 1000
Building A NULL 6/1/2011 1000
Building A Tenant C 7/1/2011 1000
Building A Tenant C 8/1/2011 1000
Building A Tenant C 9/1/2011 1000
Building A Tenant C 10/1/2011 1000
Building A Tenant C 11/1/2011 1000
Building A Tenant C 12/1/2011 1000
Building A Tenant C 1/1/2012 1000
Building A Tenant C 2/1/2012 1000
Building A Tenant C 3/1/2012 1000
Building A Tenant C 4/1/2012 1000
You will need to replace 'NULL' with either blank cells, "None", "No One", or whatever works for you. The reason you need this is so Tableau has a place to land when you scroll through each page of months or quarters.
This method also gives you the benefit of simply needing to SUM(LeaseSpace) at any point to get your PropertySize and if you drag your [Occupied by] dimension into the visualization, you'll have your PropertyVacancy for any given Month/Page.
Percent Occupied is a Calculated Field: SUM(IF CONTAINS([Occupied by],'Tenant') THEN [LeaseSpace] END) / SUM([LeaseSpace])
Let's say it's 2/1/2016 and you haven't renewed your leases with Tenants A and B. Your records for that month would look like this:
PropertyName Occupied by Month LeaseSpace
Building A Tenant C 2/1/2016 1000
Building A NULL 2/1/2016 4000

Related

Redis advice- when to group data and when to split it up

Hoping to get some sage advice from those that have been in the trenches, and can help me better understand when to keep data clustered together in Redis, and when to split it up.
I am working on a multi-tenant platform that has GPS data coming in every 3-5 seconds for each asset I track. As data is processed, we store additional information associated with the asset (i.e. is it on time, is it late, etc).
Each asset belongs to one or more tenant. For example, when tracking a family car, that car may exist for the husband, and the wife. Each needs to know where it is relative to their needs. For example, the car may be being used by the teenager and is on time for the husband to use it at 3:00 pm, but late for the wife to use it at 2:30 pm.
As an additional requirement, a single tenant may want read access to other tenants. I.E. the Dad wants to see the family car, and any teenager's cars. So the heirarchy can start to look something like this:
Super-Tenant --
--Super Tenant (Family)
--Tenant (Dad)
--Vehicle 1
--Gps:123.456,15.123
--Status:OnTime
--Vehicle 2
--Gps:123.872,15.563
--Status:Unused
--Tenant (Mom)
--Vehicle 1
--Gps:123.456,15.123
--Status:Late
--Vehicle 2
--Gps:123.872,15.563
--Status:Unused
--Tenant (Teenager)
--Vehicle 1
--Gps:123.456,15.123
--Status:Unused
--Vehicle 2
--Gps:123.872,15.563
--Status:Unused
My question has to do with the best way to store this in Redis.
I can store by tenant - I.E. I can use a Key for Dad, then have a collection of all of the vehicles he has access to. Each time a new GPS location comes in (whether for Vehicle 1 or Vehicle 2), I would update the contents of the collection. My concern is that if there are dozens of vehicles that we would be updating his collection way to often.
Or
I can store by tenant, then by vehicle. This means that when Vehicle 1's GSP location comes in I will be updating information across 3 different tenants. Not to bad.
What gives me pause is that I am working on a website for Dad to see all his vehicles. That call is going to come in and ask for all Vehicles under the Tenant of Dad. If I split out the data so it is stored by tenant/vehicle, then I will have to store the fact that Dad has 2 vehicles, then ask Redis for everything in (key1,key2,etc).
If I make it so that everything is stored in a collection under the Dad tenant, then my request to Redis would be much simpler and will be asking for everything under the key Dad.
In reality, each tenant will have between 5-100 vehicles, and we have 100's of tenants.
Based on your experience, what would be your preferred approach (please feel free to offer any not offered here).
From your question it appears you're hoping to store everything you need under one key. Redis doesn't support nested hashes as-is. There are a few recommendations from this answer on how to work around.
Based on the update cadence of the GPS data, it's best to minimize the total number of writes required. This may increase the number of operations to construct a response on read; however, adding read only slave instances should allow you to scale reads. You can tune your writes with some pipelining of updates.
From what you have described it sounds like the updates are limited to the GPS and status of a vehicle for a user. The data requested on read would be for a single user view what their set of vehicle position and status is.
I would start with a Tenant stored as a hash with the user's name, and a field referenceing the vehicles and sessions associated to the user. This is not really necessary if you take similar naming conventions, but shown as an option if additional user data needs cached.
- Tenant user-1 (Hash)
-- name: Dad (String)
-- vehicles: user-1:vehicles (String) reference to key for set of vehicles assigned.
-- sessions: user-1:sessions (String) reference to key for set of user-vehicle sessions.
The lookup of a the vehicles could be done with key formatting if none of the other tenant data is needed. The members would be references to the keys of vehicles.
- UserVechicles user-1:vehicles (Set)
-- member: vehicle-1 (String)
This would allow lookup of the details for the vehicle. Vehicles would have their position. You could include a field to reference a vehicle centric schedule of sessions similar to the user sessions below. Also you could place a vehicle name or other data if this is also required for response.
- Vehicle: vehicle-1 (Hash)
-- gps: "123.456,15.123" (String)
Store the sessions specific to a user in a sorted set. The members would be references to the keys storing session information. The score would be set to a timestamp value allowing range lookups for recent and upcoming sessions for that user.
- Schedule user-1:sessions
-- member: user-1:vehicle-1:session-1 (String)
-- score: 1638216000 (Float)
Tenant Sessions on a vehicle you could go simply with the listing of the status in a string. An alternative here is shown that would allow storing additional state of scheduled and available times if you need to support vehicle centric views of a schedule. Combining this with a sorted-set of vehicle sessions would round this out.
- Session user-1:vehicle-1:session-1 (Hash)
-- status: OnTime (String)
-- scheduled_start: 1638216000 (String) [optional]
-- scheduled_end: 1638216600 (String) [optional]
-- earliest_available: 1638215000 (String) [optional]
If you're not tracking state elsewhere you could use a hash to store the counters for the cache objects you have for when it comes time to issue a new one. Read and increment these when adding new cache objects.
- Globals: global (Hash)
-- user: 0
-- vehicle: 0
-- session: 0
For updates you would have: 200k write operations per update cycle.
100k tenants-vehicles (1000 tenants * 100 vehicles/tenant) each with
1 HSET vehicle
1 HSET session
Pipelining and tuning the number of requests in the pipeline can improve write performance, but I would anticipate you should be able to complete all writes in <2s.
For a read you would have something like: ~300 operations per user per request.
1 HGETALL user
1 ZRANGESTORE tempUSessions user-sessions LIMIT 200 (find up-to 200 sessions in a timeframe for the user)
200 HGETALL session
1 SMEMBERS user-vehicles (find all vehicles for the user)
100 HGET vehicle gps (get vehicle location for all vehicles)
Considerations:
A process to periodically remove sessions and their references after they pass would keep the memory from growing unbounded and performance consistent.
Adding some scripts to allow for easier updates to the cache when a new user or vehicle is added and for returning the state you described needing for display to a user would round this out.

USERELATIONSHIP in a measure with text column

CONTEXT:
I want to monitor payment transactions for money laundering, where payments cross multiple borders. There are a max of 6 countries shown per transaction. For each of these countries, I need to know a risk level.
I have 2 tables:
Transaction data (where there are many transactions from same country)
Country Risk (containing each country once, with an added risk classification. There are 100+ countries, and only 6 different Risk levels).
Problem:
I would like to look up the Risk Classification per country in Transaction Data. The problem is, there are 6 countries per transaction in Transaction Data. So I have to link Transaction data to Country Risk 6 times. Only 1 relationship can be active, of course.
So I tried writing the following measure:
CALCULATE(
VALUES('Country Risk'[Risk classification]);
USERELATIONSHIP('Transaction Data'[Country 2];'Country Risk'[Country Code]))
I get an error though when using the measure in a graph where I listed the countries from Transaction Data (where every country is mentioned in multiple rows) and I wanted to see the related risk categories:
A table of multiple values was supplied where a single value was expected
What am I doing wrong?
Made similar test data: https://drive.google.com/file/d/1_kJW-BpbrwCsbSpxdo7AJ3IzPy2oLWFJ/view?usp=sharing
Needed:
for every C (C1-C6) column I need to add the risk category.
For every C column I need to make a pie chart showing the number of transactions per risk category for that C column
Pie charts should filter the transaction oevrview: (
I've taked a PBI consultant about this, there is no way to get this issue solved the way I want it to (to have multiple relationships between 2 tables all acting as if they were active relationships at same time).
the only way of getting it done would be:
1. write measures (but that doesn't allow cross filtering between pie chart and table below)
2. unpivot the country columns (but that wouldn't allow to have 6 columns with risk category in table)
3. have 6 dimension tables (this solves the issue, because it allows both cross filtering between piechart and other piecharts & table. and it would allow to have 6 columns for separate risks in the table visual)
thanks for trying to help guys!

How to do performance testing with 5 users creates 5 tickets using visual studio or J meter performance testing tool

Provided 5 users credentials and ticket data in 5 rows of excel sheet and associated that data in performance script. If i need to do load testing with 5 or more virtual users. Then is that mean five users will create 5 tickets or each user will create 5 tickets .
It depends on how you configured. following are the simulations and their results:
5 users, 1 iteration: all 5 users create one ticket each (user1 -> tkt1 etc).
5 users, 2 iterations: all 5 users create 2 tickets each and both are same. (user1 -> tkt1 & user1 -> tkt1 etc).
10 users, 1 iteration: all 10 users create 1 ticket each. (user1 -> tkt1 & user6 -> tkt1) npte. here, tickets will be shared among threads.
Note: CSV data is shared by the threads. Once all entries are consumed, threads start picking the data from the beginning again, unless you set Recycle on EOF to false (by default, true)

How to restrict record from Team to Team in MS CRM 2015

I have a question & I think it's very common question, I gone through many blogs & white paper but didn't get any straight answer.
Say I have the below Org structure:
Org 1 - BU 1 - Sales VP - Sales Manager Team A - Sales Person Team A.
Org 1 - BU 1 - Sales VP - Sales Manager Team B - Sales Person Team B.
I don't want that Team A can see any accounts or any records being created by Team B & vice-versa but Sales VP can see all the records.
Approach A: Create a plugin/workflow & share the record accordingly.
Approach B: Create a new BU which I don't want.
Please, let me know if is there any other way to achieve this?
Thanks in advance.
Approach B is correct
ROOT BU - Sales VP
CHILD BU A - Team A CHILD BU B - Team B
This is exactly the situation BUs are meant for

Customer Filtered by Sales Representative but Showing Invoices for all Sales Representatives

I'm trying to replace our current AR report which shows all invoices outstanding by customer for a particular sales representative.
The issue is that each customer may have multiple sales representatives; however, since the Sales Representative ID is stored at the invoice level the report only displays that sales representatives sales to their customer.
What I would like to do is display on the AR report all invoices outstanding for all sales reps for each customer that a particular rep visits regardless of the sales representative making the sale.
So the sales rep will only see customers that he has outstanding balances with on his report but will also see other balances from that other reps may have outstanding with his customers.
How can I achieve this?
I suspect it has something to do with a parameter and creating a calculated field which lumps the sales reps for each invoice together for a customer and then doing a contains filter; but I can't figure out how to make that first calculation.
Additional Details:
CUSTOMER ID CUSTOMER NAME INVOICE NO SALESPERSON ID AMOUNT OTSNDNG AR BUCKET
CUST01 Customer 1 INV01 JAMES 100 31-60
CUST01 Customer 1 INV02 JAMES 100 61-90
CUST01 Customer 1 INV03 BRIAN 100 31-60
CUST01 Customer 1 INV04 MARK 100 CURRENT
CUST02 Customer 2 INV05 MARK 100 61-90
CUST02 Customer 2 INV06 JAMES 100 31-60
CUST03 Customer 3 INV07 MARK 100 31-60
CUST03 Customer 3 INV08 BRIAN 100 61-90
In the above table, when running an accounts receivable report for Brian Invoices 1-4 and 7-8 should show up as he sells to both of these customers. All invoices should show up on Mark's AR as he sells to all three customers and James should see the invoices for Customer 1 and 2.
I would attach a file to the question with this data in a spreadsheet if I could.
I believe the best way to achieve this is using parameters and conditional filters.
First, create a parameter 'rep'. Define it as list, and import [SALESPERSON] values to it.
Now the trick part, you want to filter the clients that has ever been visited by a specific salesperson. This is how you do that on Tableau:
1- Create a calculated field [marker]. Use the formula:
IF [SALESPERSON] = [rep]
THEN 1
ELSE 0
END
Note this will basically put a 1 marker on the lines of the selected salesperson
2- Drag [CUSTOMER ID] to filter
3- Go to tab 'Condition'
4- Use By field: [marker], Sum, >, 0
This will basically run a calculation. For each customer, it will get all [marker] entries, sum all them. Those who are above zero (meaning, there is at least one 1 marker) will be kept, those who are zero are eliminated
Let me know if this doesn't work, or you have any question

Resources