Calculating total revenue lost in returns with Superstore dataset - tableau-api

I am attempting to create a parameter that allows me to custom filter for Sales, Units, Profit, Orders, Returns, and Return Units. I'm running into an issue when creating the calculated field that calculates return $ and return units. The result I am getting doesn't seem to be accurate.
I have created a Parameter with the above list called [Choose KPI].
I thought I would be able to create calculated fields for [Returned $] and [Returned Units]:
IF [Returned] = 'Yes' THEN [Sales] END
and
IF [Returned] = 'Yes' THEN [Quantity] END
Which would make my calculated field for [Choose KPI]:
CASE [Parameters].[Choose KPI]
WHEN "Sales" THEN SUM([Sales])
WHEN "Units" THEN SUM([Quantity])
WHEN "Profit" THEN SUM([Profit])
WHEN "Orders" THEN COUNT([Order ID])
WHEN "Returns" THEN SUM([Returns $])
WHEN "Return Units" THEN SUM([Returned Units])
END
Rather than returns being associated with product ID, they appear to be linked only with the order ID, which creates duplicate values when there were multiple items on an order (are we assuming all items in the order were returned when [Returned] = 'Yes'?), causing the sum of [Returns $] to be inflated.
How can I create a filter that uses the distinct Order ID to calculate total returns and returned units?

In Tableau, you can use the "Group" option in the "Analysis" menu to create a new field that groups your data by the "Order ID" field. Then, you can use the "COUNTD" function to count the number of unique "Order ID" values, which will give you the total number of returned orders.
To calculate the total returned units, you can create a calculated field that multiplies the quantity of each returned item by the number of unique items returned per order. You can use the COUNTD([Order ID]) and SUM(IF [Returned] = 'Yes' THEN [Quantity] END) in the calculation.
In the [Choose KPI] field, you can use the following calculation:
CASE [Parameters].[Choose KPI]
WHEN "Sales" THEN SUM([Sales])
WHEN "Units" THEN SUM([Quantity])
WHEN "Profit" THEN SUM([Profit])
WHEN "Orders" THEN COUNTD([Order ID])
WHEN "Returns" THEN SUM(IF [Returned] = 'Yes' THEN [Sales] END)
WHEN "Return Units" THEN SUM(IF [Returned] = 'Yes' THEN [Quantity] END) * COUNTD([Order ID])
END
This way, you will be able to filter your data based on the different KPIs you've defined, and the calculations for returned sales and units will be based on the distinct Order ID values.
(Answer by https://chat.openai.com/chat and formatted by me.)

Related

What does filter mean?

select driverid, count(*)
from f1db.results
where position is null
group by driverid order by driverid
My thought: first find out all the records that position is null then do the aggregate function.
select driverid, count(*) filter (where position is null) as outs
from f1db.results
group by driverid order by driverid
First time, I meet with filter clause, not sure what does it mean?
Two code block results are different.
Already googled, seems don't have many tutorials about the FILTER. Kindly share some links.
A more helpful term to search for is aggregate filters, since FILTER (WHERE) is only used with aggregates.
Filter clauses are an additional filter that is applied only to that aggregate and nowhere else. That means it doesn't affect the rest of the columns!
You can use it to get a subset of the data, like for example, to get the percentage of cats in a pet shop:
SELECT shop_id,
CAST(COUNT(*) FILTER (WHERE species = 'cat')
AS DOUBLE PRECISION) / COUNT(*) as "percentage"
FROM animals
GROUP BY shop_id
For more information, see the docs
FILTER ehm... filters the records which should be aggregated - in your case, your aggregation counts all positions that are NULL.
E.g. you have 10 records:
SELECT COUNT(*)
would return 10.
If 2 of the records have position = NULL
than
SELECT COUNT(*) FILTER (WHERE position IS NULL)
would return 2.
What you want to achieve is to count all non-NULL records:
SELECT COUNT(*) FILTER (WHERE position IS NOT NULL)
In the example, it returns 8.

Tableau:Create a calculated field using Case statement and case statement uses a logical calculation

I have a question regarding tableau calculated field.
I am using Sample Super Store data. Below is my questions
I want to Categorize Sales into 'Low Sales','High Sales' and 'Super Sales' based on below
using Case Statements
SUM(Sales)>500000 then categorize as 'Less Sales'
(Sales) between 500000 and 1000000 then 'High Sales'
Else SUM(Sales)>1000000 then 'Super Sales'
After categorising I need to find out the count of [Order] under Super Sales '
Try below steps:
Create 3 sets for Order ID 3 conditions:
Set 1:
Right Click Order ID --> Create --> Set Here move to the condition tab and select condition for Sales and value is <50000
Similarly create 2 more sets.
Create a calculated field Display and write below code:
IF [Set 1]=TRUE
THEN "Less Sales"
ELSEIF [Set 2]=TRUE
THEN "High Sales"
ELSEIF [Set 3]=TRUE
THEN "Super Sales"
END
Place the calcualte field on Rows and Order ID on Columns
For order ID select the aggrigation Count Distinct
Now you should be able to see the order count for all sales

Tableau group by multiple groups

I have created two groups on a customer level (all with distinct customer IDs) based on some criterias. But I am having difficulties grouping these on a group level (group ID). The data structure is a follows: a customer has one customer ID and a group ID. The customer ID is distinct but the group ID is not; i.e. multiple customers (customer IDs) are part of a group and therefore have the same group ID.
My tableau code looks something like this:
IF [Sales] >= 200000 and [Category] = 'A'
OR [CAC] <= 10000 and [Category] = 'A'
THEN 'Good customer'
ELSE 'Bad customer'
END
The above code gives me the grouping on a customer level. However, I want to see the group level, i.e. if just one customer from a group is a 'Good customer' then the entire group should be classified as a 'Good customer'. This means that if just one customer from the group is classied as a 'Good customer' then all the [Sales] and [CAC] of the customers within the particular group should be summed up on a group level and displayed under 'Good customer' on a group level instead of on customer level.
Try this:
Create a field [GoodCustomer] with this formula:
IF [Sales] >= 200000 AND [Category] = 'A'
OR [CAC] <= 10000 AND [Category] = 'A'
THEN 1
ELSE 0
END
This is your condition but assigns a numeric value to it (1 = good customer, 0 = bad customer)
Create a field [GoodGroup] with this formula:
{fixed [Group]: IIF(SUM([GoodCustomer]) > 0, True, False)}
For each group this checks if the sum of [GoodCustomer] is greater 0 (which means that at least one customer was good). If this is true it sets it to True (or use 'Good Group') if it is false, set it to False (or 'Bad Group')
This should give you what you described above.

Tableau - Calculating average where date is less than value from another data source

I am trying to calculate the average of a column in Tableau, except the problem is I am trying to use a single date value (based on filter) from another data source to only calculate the average where the exam date is <= the filtered date value from the other source.
Note: Parameters will not work for me here, since new date values are being added constantly to the set.
I have tried many different approaches, but the simplest was trying to use a calculated field that pulls in the filtered exam date from the other data source.
It successfully can pull the filtered date, but the formula does not work as expected. 2 versions of the calculation are below:
IF DATE(ATTR([Exam Date])) <= DATE(ATTR([Averages (Tableau Test Scores)].[Updated])) THEN AVG([Raw Score]) END
IF DATEDIFF('day', DATE(ATTR([Exam Date])), DATE(ATTR([Averages (Tableau Test Scores)].[Updated]))) > 1 THEN AVG([Raw Score]) END
Basically, I am looking for the equivalent of this in SQL Server:
SELECT AVG([Raw Score]) WHERE ExamDate <= (Filtered Exam Date)
Below a workbook that shows an example of what I am trying to accomplish. Currently it returns all blanks, likely due to the many-to-one comparison I am trying to use in my calculation.
Any feedback is greatly appreciated!
Tableau Test Exam Workbook
I was able to solve this by using Custom SQL to join the tables together and calculate the average based on my conditions, to get the column results I wanted.
Would still be great to have this ability directly in Tableau, but whatever gets the job done.
Edit:
SELECT
[AcademicYear]
,[Discipline]
--Get the number of student takers
,COUNT([Id]) AS [Students (N)]
--Get the average of the Raw Score
,CAST(AVG(RawScore) AS DECIMAL(10,2)) AS [School Mean]
--Get the number of failures based on an "adjusted score" column
,COUNT([AdjustedScore] < 70 THEN 1 END) AS [School Failures]
--This is the column used as the cutoff point for including scores
,[Average_Update].[Updated]
FROM [dbo].[Average] [Average]
FULL OUTER JOIN [dbo].[Average_Update] [Average_Update] ON ([Average_Update].[Id] = [Average].UpdateDateId)
--The meat of joining data for accurate calculations
FULL OUTER JOIN (
SELECT DISTINCT S.[Id], S.[LastName], S.[FirstName], S.[ExamDate], S.[RawScoreStandard], S.[RawScorePercent], S.[AdjustedScore], S.[Subject], P.[Id] AS PeriodId
FROM [StudentScore] S
FULL OUTER JOIN
(
--Get only the 1st attempt
SELECT DISTINCT [NBOMEId], S2.[Subject], MIN([ExamDate]) AS ExamDate
FROM [StudentScore] S2
GROUP BY [NBOMEId],S2.[Subject]
) B
ON S.[NBOMEId] = B.[NBOMEId] AND S.[Subject] = B.[Subject] AND S.[ExamDate] = B.[ExamDate]
--Group in "Exam Periods" based on the list of periods w/ start & end dates in another table.
FULL OUTER JOIN [ExamPeriod] P
ON S.[ExamDate] = P.PeriodStart AND S.[ExamDate] <= P.PeriodEnd
WHERE S.[Subject] = B.[Subject]
GROUP BY P.[Id], S.[Subject], S.[ExamDate], S.[RawScoreStandard], S.[RawScorePercent], S.[AdjustedScore], S.[NBOMEId], S.[NBOMELastName], S.[NBOMEFirstName], S.[SecondYrTake]) [StudentScore]
ON
([StudentScore].PeriodId = [Average_Update].ExamPeriodId
AND [StudentScore].Subject = [Average].Subject
AND [StudentScore].[ExamDate] <= [Average_Update].[Updated])
--End meat
--Joins to pull in relevant data for normalized tables
FULL OUTER JOIN [dbo].[Student] [Student] ON ([StudentScore].[NBOMEId] = [Student].[NBOMEId])
INNER JOIN [dbo].[ExamPeriod] [ExamPeriod] ON ([Average_Update].ExamPeriodId = [ExamPeriod].[Id])
INNER JOIN [dbo].[AcademicYear] [AcademicYear] ON ([ExamPeriod].[AcademicYearId] = [AcademicYear].[Id])
--This will pull only the latest update entry for every academic year.
WHERE [Updated] IN (
SELECT DISTINCT MAX([Updated]) AS MaxDate
FROM [Average_Update]
GROUP BY[ExamPeriodId])
GROUP BY [AcademicYear].[AcademicYearText], [Average].[Subject], [Average_Update].[Updated],
ORDER BY [AcademicYear].[AcademicYearText], [Average_Update].[Updated], [Average].[Subject]
I couldn't download your file to test with your data, but try reversing the order of taking the average ie
average(IF DATE(ATTR([Exam Date])) <= DATE(ATTR([Averages (Tableau Test Scores)].[Updated]) then [Raw Score]) END)
as written, I believe you'll be averaging the data before returning it from the if statement, whereas you want to return the data, then average it.

How to split a single column into two based on where clause

Can anyone suggest me how to split a single column into two? Here's my table named ax_cash_book.
I want to split the amount column into two columns named "Credit" where trans_type ='Credit' and "Debit" where trans_type = 'Debit'. I tried to write a query like this :
select amount as Credit, amount as Debit from ax_cash_book
But I am unable to find the appropriate place for including the where clause. Please suggest me some query to sort out the problem.
Thank you in advance!!
You can use the CASE ... WHEN statement for this:
SELECT
CASE WHEN trans_type = 'Credit' THEN amount ELSE 0 END AS Credit,
CASE WHEN trans_type = 'Debit' THEN amount ELSE 0 END AS Debit
FROM ax_cash_book
What this will do is when the trans_type column equals "Credit", then use the amount database field.
I take it that if the value is a credit then there is no debit, hence ELSE 0.
The same will apply for the Debit field.