Tableau - How check if a value equals a value from another row and column - tableau-api

I have the following table:
+------------+--------------+---------+---------+---------+
| Category | Subcategory |FruitName| Date1 | Date2 |
+------------+--------------+---------+---------+---------+
| A | 1 | Foo | 2011 | 2017 |
| | +---------+---------+---------+
| | |Pineapple| 2011 | 2013 |
| | +---------+---------+---------+
| | | Apple | 2017 | 2018 |
| +--------------+---------+---------+---------+
| | 2 | Peach | 2014 | 2015 |
| | +---------+---------+---------+
| | | Orange | 2015 | 2018 |
| | +---------+---------+---------+
| | | Banana | 2009 | 2013 |
+------------+--------------+---------+---------+---------+
I'd like to display the fruit names where Date1 from one row == Date2 from another row, but only if they are equals within the same Subcategory. In the table above, this filter should retrieve the rows based on those criterias:
And the final table would look like this:
+------------+--------------+---------+---------+---------+
| Category | Subcategory |FruitName| Date1 | Date2 |
+------------+--------------+---------+---------+---------+
| A | 1 | Foo | 2011 | 2017 |
| | +---------+---------+---------+
| | | Apple | 2017 | 2018 |
| +--------------+---------+---------+---------+
| | 2 | Peach | 2014 | 2015 |
| | +---------+---------+---------+
| | | Orange | 2015 | 2018 |
+------------+--------------+---------+---------+---------+
How can I possibly achieve this?

Your logic provided doesnot match with the output provided. If you are after the output, your logic should be:
SELECT f1.* from fruits f1 JOIN fruits f2
ON f1.Subcategory=f2.Subcategory
WHERE f1.Date1=f2.Date2 OR f1.Date2 = f2.Date1;
If your data source supports custom SQL, you can straight away use the above query. If not you can still achieve it in Tableau using a Full Outer Join and a calculated Field.(Tableau doesn't support OR condition in Joins.)
Create a self full outerjoin with the following criteria
Create a calculation called 'FILTER' as below
Apply a datasource filter to keep only 'FILTER' = True
Hide Fields from the rightside connection and you will have the required output.

Related

select inside select and minimizing running time in POSTGRESQL

I am trying to calculate the total booking number and the percentage for each hotel per year using POSTGRESQL. Here is my code:
WITH distribution_per_year AS
(
SELECT hotel, arrival_date_year,
COUNT(*) AS booking_by_hotel,
(SELECT COUNT(*) AS total_booking FROM "Full_Data" )
FROM "Full_Data"
GROUP BY hotel, arrival_date_year
)
SELECT hotel, arrival_date_year, booking_by_hotel, total_booking,
round(booking_by_hotel *100.00 / total_booking , 2) as percent
FROM distribution_per_year
and it worked, it gives me the results as I wanted
| hotel | arrival_date_year | booking_by_hotel | total_booking | percent |
|:------ |:----------------- |:---------------- |:------------- |:--------|
| Hotel1 | 2015 | 6526 | 100561 | 6.49 |
| Hotel1 | 2016 | 33210 | 100561 | 33.02 |
| Hotel1 | 2017 | 20064 | 100561 | 19.95 |
| Hotel2 | 2015 | 6758 | 100561 | 6.72 |
| Hotel2 | 2016 | 22434 | 100561 | 22.31 |
| Hotel2 | 2017 | 11569 | 100561 | 11.50 |
My question is: I noticed it takes time to run this code. I think it's because it repeats the subquery every time it group by
(SELECT COUNT(*) AS total_booking FROM "Full_Data" )
Is there a way to enhance this code??

SQL server left join not returning expected records from left table

I have two objects within a SQl Server 2008 R2 database, which I am trying to join together with a left join but I am unable to get the left join to return all records from the table.
1 table - tt_activityoccurrence
1 view - vw_academicweeks
The vw_academicweeks, is a view that contains for each academic year a week number, and the first day and last day of the week and contains 52 records for each academic year.
tt_activityoccurrence is a table which contains occurrences of lessons within a year, lessons will not occur in all 52 weeks of the year.
With my query I am trying to return all instances from the vw_academicweeks view to return the following information
+------------+------------+------------+------------+---------+
| ActivityID | WeekStart | StartTime | EndTime | week_no |
+------------+------------+------------+------------+---------+
| 59936 | 04/09/2017 | 05/09/2017 | 05/09/2017 | 6 |
| 59936 | 11/09/2017 | 12/09/2017 | 12/09/2017 | 7 |
| 59936 | 18/09/2017 | 19/09/2017 | 19/09/2017 | 8 |
| 59936 | 25/09/2017 | 26/09/2017 | 26/09/2017 | 9 |
| 59936 | 02/10/2017 | 03/10/2017 | 03/10/2017 | 10 |
| 59936 | 09/10/2017 | 10/10/2017 | 10/10/2017 | 11 |
| 59936 | 16/10/2017 | 17/10/2017 | 17/10/2017 | 12 |
| 59936 | Null | Null | Null | 13 |
| 59936 | 30/10/2017 | 31/10/2017 | 31/10/2017 | 14 |
| 59936 | 06/11/2017 | 07/11/2017 | 07/11/2017 | 15 |
| 59936 | 13/11/2017 | 14/11/2017 | 14/11/2017 | 16 |
| 59936 | 20/11/2017 | 21/11/2017 | 21/11/2017 | 17 |
| 59936 | 27/11/2017 | 28/11/2017 | 28/11/2017 | 18 |
| 59936 | 04/12/2017 | 05/12/2017 | 05/12/2017 | 19 |
| 59936 | 11/12/2017 | 12/12/2017 | 12/12/2017 | 20 |
| 59936 | 18/12/2017 | 19/12/2017 | 19/12/2017 | 21 |
| 59936 | Null | Null | Null | 22 |
| 59936 | Null | Null | Null | 23 |
+------------+------------+------------+------------+---------+
With the left join I can return all values except the nulls, so that the week_no column is missing rows, 13,22 and 23. I have also tried this with an outer join but receive the same information.
I feel I am missing something obvious but it is escaping me at the moment.
select
ttao.ActivityID
,dateadd(dd,datediff(dd,0,DATEADD(dd, -(DATEPART(dw, ttao.StartTime)-1), ttao.StartTime)),0) WeekStart
,ttao.StartTime
,ttao.EndTime
,aw.week_no
from
vw_AcademicWeeks AW
left join TT_ActivityOccurrence TTAO on
(dateadd(dd,datediff(dd,0,DATEADD(dd, -(DATEPART(dw, ttao.StartTime)-1), ttao.StartTime)),0))=aw.ay_start
where
ay_code='1718' and
TTAO.ActivityID='59936'
order by aw.week_no asc
Your where clause makes it an inner join by eliminating rows outside of the scope of your join. You need to move this logic up to your join statement. Note, I didn't validate your join condiditon (the dateadd...datediff logic)
select
ttao.ActivityID
,dateadd(dd,datediff(dd,0,DATEADD(dd, -(DATEPART(dw, ttao.StartTime)-1), ttao.StartTime)),0) WeekStart
,ttao.StartTime
,ttao.EndTime
,aw.week_no
from
vw_AcademicWeeks AW
left join TT_ActivityOccurrence TTAO on
(dateadd(dd,datediff(dd,0,DATEADD(dd, -(DATEPART(dw, ttao.StartTime)-1), ttao.StartTime)),0)) = aw.ay_start
and ay_code='1718'
and TTAO.ActivityID='59936'
order by aw.week_no asc

Calculate LAG variable after filtering in Tableau

I have a dataset with 4 columns: ID (unique identifier of user), Year, Country and Level in this format:
+----+------+---------+-------+
| ID | Year | Country | Level |
+----+------+---------+-------+
| 1 | 2015 | USA | 1 |
| 1 | 2016 | China | 2 |
| 2 | 2015 | China | 2 |
| 2 | 2016 | Russia | 2 |
| 3 | 2015 | Russia | 1 |
| 3 | 2016 | China | 2 |
| 4 | 2015 | USA | 2 |
| 4 | 2016 | USA | 3 |
| 5 | 2014 | China | 1 |
| 5 | 2016 | USA | 2 |
| 6 | 2015 | USA | 1 |
| 6 | 2016 | USA | 2 |
| 7 | 2015 | Russia | 2 |
| 7 | 2016 | China | 3 |
+----+------+---------+-------+
The user will be able to filter the dataset by country.
I want to create a table using the country filter that shows in a column if a user was the previous year in any of the countries selected aggregated by the level variable, apart from other variables only affected by the current country filter.
For example E.g., if I select China and USA:
+----+------+---------+-------+-----------------+
| ID | Year | Country | Level | In selection PY |
+----+------+---------+-------+-----------------+
| 1 | 2015 | USA | 1 | No |
| 1 | 2016 | China | 2 | Yes |
| 2 | 2015 | China | 2 | No |
| 3 | 2016 | China | 2 | No |
| 4 | 2015 | USA | 2 | No |
| 4 | 2016 | USA | 3 | Yes |
| 5 | 2014 | China | 1 | No |
| 5 | 2016 | USA | 2 | No |
| 6 | 2015 | USA | 1 | No |
| 6 | 2016 | USA | 2 | Yes |
| 7 | 2016 | China | 3 | No |
+----+------+---------+-------+-----------------+
The aggregated result will be:
+-------+-------------------+-----------------+
| Level | Number of records | In selection PY |
+-------+-------------------+-----------------+
| 1 | 3 | 0 |
| 2 | 6 | 2 |
| 3 | 2 | 1 |
+-------+-------------------+-----------------+
Do you know any way to calculate this aggregated table efficiently? (this would be done in a dataset with millions of rows, with a variable set of countries to be selected)
I found a solution, will post in case it is helpful for someone else:
I change the Country filter to "Add to Context" and created this variable:
In Selection PY: if Year = 2016 then
{fixed [ID]:min(if Year = 2015 then 1 END)}
elseif Year = 2015 then
{fixed [ID]:min(if Year = 2014 then 1 END)}
elseif Year = 2014 then
{fixed [ID]:min(if Year = 2013 then 1 END)}
In this way the variable Selection PY is dynamically calculated according to the country filter.
It is only necessary to know in advance which years are stored in the dataset (or add more years to be safe).

Tableau - Calculated field for difference between date and maximum date in table

I have the following table that I have loaded in Tableau (It has only one column CreatedOnDate)
+-----------------+
| CreatedOnDate |
+-----------------+
| 1/1/2016 |
| 1/2/2016 |
| 1/3/2016 |
| 1/4/2016 |
| 1/5/2016 |
| 1/6/2016 |
| 1/7/2016 |
| 1/8/2016 |
| 1/9/2016 |
| 1/10/2016 |
| 1/11/2016 |
| 1/12/2016 |
| 1/13/2016 |
| 1/14/2016 |
+-----------------+
I want to be able to find the maximum date in the table, compare it with every date in the table and get the difference in days. For the above table, the maximum date in table is 1/14/2016. Every date is compared to 1/14/2016 to find the difference.
Expected Output
+-----------------+------------+
| CreatedOnDate | Difference |
+-----------------+------------+
| 1/1/2016 | 13 |
| 1/2/2016 | 12 |
| 1/3/2016 | 11 |
| 1/4/2016 | 10 |
| 1/5/2016 | 9 |
| 1/6/2016 | 8 |
| 1/7/2016 | 7 |
| 1/8/2016 | 6 |
| 1/9/2016 | 5 |
| 1/10/2016 | 4 |
| 1/11/2016 | 3 |
| 1/12/2016 | 2 |
| 1/13/2016 | 1 |
| 1/14/2016 | 0 |
+-----------------+------------+
My goal is to create this Difference calculated field. I am struggling to find a way to do this using DATEDIFF.
And help would be appreciated!!
woodhead92, this approach would work, but means you have to use table calculations. Much more flexible approach (available since v8) is Level of Details expressions:
First, define a MAX date for the whole dataset with this calculated field called MaxDate LOD:
{FIXED : MAX(CreatedOnDate) }
This will always calculate the maximum date on table (will overwrite filters as well, if you need to reflect them, make sure you add them to context.
Then you can use pretty much the same calculated field, but no need for ATTR or Table Calculations:
DATEDIFF('day', [CreatedOnDate], [MaxDate LOD])
Hope this helps!

Subtract fields of a column - Tableau

I would like to subtract promoters and detractors in Tableau by creating a new column. Thanks for all the help!
Customer Type Table (I would like to create the NPS field as shown below):
+---------+------------+----------+-----------+--------------+
| Quarter | Detractors | Passives | Promoters | NPS |
+---------+------------+----------+-----------+--------------+
| Q1 15 | 40.56 | 23.56 | 35.79 | =35.79-40.56 |
| ... | ... | ... | ... | ... |
+---------+------------+----------+-----------+--------------+
Simply create a calculated field (called NPS):
[Promoters] - [Detractors]
This will add a new field to every row of your partition called NPS.
Check out the Tableau online help on calculated fields - this is a skill well worth learning.
I understand the OPs question. The data comes in like this:
+---------+---------------+------+
| Quarter | Customer Type | Score|
+---------+------------+---------+
| Q1 15 | Detractors | 25 |
| Q1 15 | Promoters | 32 |
| Q1 15 | Passives | 45 |
| Q1 15 | Detractors | 17 |
| Q1 15 | Detractors | 28 |
| ... | ... | ... |
+---------+------------+---------+
And when brought into Tableau, the [Customer Type] field is put in the Column shelf and this arranges the data like the table below. The OP wants to calculate the [NPS] column (Promoters - Detractors).
+---------+------------+----------+-----------+--------------+
| Quarter | Detractors | Passives | Promoters | NPS |
+---------+------------+----------+-----------+--------------+
| Q1 15 | 40.56 | 23.56 | 35.79 | =35.79-40.56 |
| ... | ... | ... | ... | ... |
+---------+------------+----------+-----------+--------------+
I hope this clarifies. I am stuck with a similar situation (I want a column that shows the difference between 2015 and 2016):
+---------+-------+-------+------------+
| Measure | 2015 | 2016 | Difference |
+---------+---------------+------------+
| # Hires | 100 | 115 | 15 |
| # Terms | 9 | 6 | 3 |
+---------+---------------+------------+
I believe the steps are similar. I hope someone can help.