Tableau month-based bar chart for data with date range - tableau-api

I have data similar to the below:
id | start | end | name
1 | 2017-01-15 | 2017-03-30 | Item 1
2 | 2017-02-01 | 2017-05-15 | Item 2
3 | 2017-02-15 | 2017-04-01 | Item 3
I want to represent this as a bar chart with Month on the horizontal axis, and count on the vertical axis, where the value is computed by how many items fall within that month. In the above data set, January would have a value of 1, February would have a value of 3, March would have a value of 3, April would have a value of 2, and May would have a value of 1.
The closest I can get right now is to represent the count of items with the start or end date, but I want the month to represent how many items fall within that month.
I haven't found a way to do this in Tableau without restructuring my data set to have each current row restated for each month, which I don't have the luxury to do. Is this possible at all?

One solution could be to have 12 calculated fields like below
id | start | end | name | Jan | Feb | Mar | Apr | May...
1 | 2017-01-15 | 2017-03-30 | Item 1 | 1 | 1 | 1 | 0 | 0
2 | 2017-02-01 | 2017-05-15 | Item 2 | 0 | 1 | 1 | 1 | 1
3 | 2017-02-15 | 2017-04-01 | Item 3 | 0 | 1 | 1 | 1 | 0
Definition of calculated fields -
'Jan' is DATENAME('month',[start]) <= 1 & 1 <=
DATENAME('month',[end])
'Feb' is DATENAME('month',[start]) <= 2 & 2 <=
DATENAME('month',[end]) and so on...
Then using Pivot option in Tableau, convert it to something like
name | Month | Count
Item1 | Jan | 1
Item2 | Jan | 0
Item3 | Jan | 0
...
Item1 | Feb | 1
Item2 | Feb | 1
Item3 | Feb | 1
...
Item1 | Mar | 1
Item2 | Mar | 1
Item3 | Mar | 1
...
Drag Month to 'Columns' and SUM(Count) to 'Rows' to generate the final visualization.
Hope this helps!

Related

How to order the result of ROLLUP by each groups total

So I have the following query that produces the following result:
actname | year | tickets
---------------+----------+---------
Join Division | 2016 | 2
Join Division | 2018 | 2
Join Division | 2020 | 3
Join Division | Total | 7 <<<
QLS | 2018 | 2
QLS | 2019 | 1
QLS | Total | 3 <<<
Scalar Swift | 2017 | 3
Scalar Swift | 2018 | 1
Scalar Swift | 2019 | 1
Scalar Swift | Total | 5 <<<
The Selecter | 2017 | 4
The Selecter | 2018 | 4
The Selecter | Total | 8 <<<
The Where | 2016 | 1
The Where | 2017 | 3
The Where | 2018 | 5
The Where | 2020 | 4
The Where | Total | 13 <<<
ViewBee 40 | 2017 | 3
ViewBee 40 | 2018 | 1
ViewBee 40 | Total | 4 <<<
The problem I have is that I want to re-order the results such that the group with the lowest Total occurs first, such that the results would look like this:
actname | year | tickets
---------------+----------+---------
QLS | 2018 | 2
QLS | 2019 | 1
QLS | Total | 3 <<<
ViewBee 40 | 2017 | 3
ViewBee 40 | 2018 | 1
ViewBee 40 | Total | 4 <<<
Scalar Swift | 2017 | 3
Scalar Swift | 2018 | 1
Scalar Swift | 2019 | 1
Scalar Swift | Total | 5 <<<
Join Division | 2016 | 2
Join Division | 2018 | 2
Join Division | 2020 | 3
Join Division | Total | 7 <<<
The Selecter | 2017 | 4
The Selecter | 2018 | 4
The Selecter | Total | 8 <<<
The Where | 2016 | 1
The Where | 2017 | 3
The Where | 2018 | 5
The Where | 2020 | 4
The Where | Total | 13 <<<
I'm obtaining the results by using the following GROUP:
GROUP BY actname, ROLLUP(year)
Which is combining all the ticket amounts of the same actname and year together.
I can provide the full query if necessary!
Thanks
Using window function (which is sum() in this case) you can set value to groups (groups are partitioned by actname column) , so now every group from actname column, have same value, as its own row where year='Total'.
Then simply sort by that new column, something like this:
with t(actname, year, tickets) as (
VALUES
('Join Division','2016',2),
('Join Division','2018',2),
('Join Division','2020',3),
('Join Division','Total',7),
('QLS','2018',2),
('QLS','2019',1),
('QLS','Total',3 ),
('Scalar Swift','2017',3),
('Scalar Swift','2018',1),
('Scalar Swift','2019',1),
('Scalar Swift','Total',5 ),
('The Selecter','2017',4),
('The Selecter','2018',4),
('The Selecter','Total',8 ),
('The Where','2016',1),
('The Where','2017',3),
('The Where','2018',5),
('The Where','2020',4),
('The Where','Total',13 ),
('ViewBee 40','2017',3),
('ViewBee 40','2018',1),
('ViewBee 40','Total',4 )
)
SELECT * FROM (
select *, sum(case when year = 'Total' then tickets end) over(partition by actname) sm from t
) tt
ORDER BY sm, year

Cumulative sum of multiple window functions

I have a table with the structure:
id | date | player_id | score
--------------------------------------
1 | 2019-01-01 | 1 | 1
2 | 2019-01-02 | 1 | 1
3 | 2019-01-03 | 1 | 0
4 | 2019-01-04 | 1 | 0
5 | 2019-01-05 | 1 | 1
6 | 2019-01-06 | 1 | 1
7 | 2019-01-07 | 1 | 0
8 | 2019-01-08 | 1 | 1
9 | 2019-01-09 | 1 | 0
10 | 2019-01-10 | 1 | 0
11 | 2019-01-11 | 1 | 1
I want to create two more columns, 'total_score', 'last_seven_days'.
total_score is a rolling sum of the player_id score
last_seven_days is the score for the last seven days including to and prior to the date
I have written the following SQL query:
SELECT id,
date,
player_id,
score,
sum(score) OVER all_scores AS all_score,
sum(score) OVER last_seven AS last_seven_score
FROM scores
WINDOW all_scores AS (PARTITION BY player_id ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING),
last_seven AS (PARTITION BY player_id ORDER BY id ROWS BETWEEN 7 PRECEDING AND 1 PRECEDING);
and get the following output:
id | date | player_id | score | all_score | last_seven_score
------------------------------------------------------------------
1 | 2019-01-01 | 1 | 1 | |
2 | 2019-01-02 | 1 | 1 | 1 | 1
3 | 2019-01-03 | 1 | 0 | 2 | 2
4 | 2019-01-04 | 1 | 0 | 2 | 2
5 | 2019-01-05 | 1 | 1 | 2 | 2
6 | 2019-01-06 | 1 | 1 | 3 | 3
7 | 2019-01-07 | 1 | 0 | 4 | 4
8 | 2019-01-08 | 1 | 1 | 4 | 4
9 | 2019-01-09 | 1 | 0 | 5 | 4
10 | 2019-01-10 | 1 | 0 | 5 | 3
11 | 2019-01-11 | 1 | 1 | 5 | 3
I have realised that I need to change this
last_seven AS (PARTITION BY player_id ORDER BY id ROWS BETWEEN 7 PRECEDING AND 1 PRECEDING)
to instead of being 7, to use some sort of date format because just having the number 7 will introduce errors.
i.e. it would be nice to be able to do date - 2days or date - 6days
I also would like to add columns such as 3 months, 6 months, 12 months later down the track and so need it to be able to be dynamic.
DEMO
demo:db<>fiddle
Solution for Postgres 11+:
Using RANGE interval as #LaurenzAlbe did
Solution for Postgres <11:
(just presenting the "days" part, the "all_scores" part is the same)
Joining the table against itself on the player_id and the relevant date range:
SELECT s1.*,
(SELECT SUM(s2.score)
FROM scores s2
WHERE s2.player_id = s1.player_id
AND s2."date" BETWEEN s1."date" - interval '7 days' AND s1."date" - interval '1 days')
FROM scores s1
You need to use a window by RANGE:
last_seven AS (PARTITION BY player_id
ORDER BY date
RANGE BETWEEN INTERVAL '7 days' PRECEDING
AND INTERVAL '1 day' PRECEDING)
This solution will work only from v11 on.

Date have no data and will show the date with Zero Data in Crystal Reports

I have an output like this on my Crystal Reports:
Example:
Date(as group)| Hours | Counts
----------------------------------
01-Feb-2018 | 20 | 5
03-Feb-2018 | 25 | 3
04-Feb-2018 | 22 | 3
05-Feb-2018 | 21 | 2
07-Feb-2018 | 28 | 1
10-Feb-2018 | 23 | 1
If you can see, there are days that missing because no data/empty, but I want the missing days to be shown and have a value of zero:
Date | Hours | Counts
----------------------------------
01-Feb-2018 | 20 | 5
02-Feb-2018 | 0 | 0
03-Feb-2018 | 25 | 3
04-Feb-2018 | 22 | 3
05-Feb-2018 | 21 | 2
06-Feb-2018 | 0 | 0
07-Feb-2018 | 28 | 1
08-Feb-2018 | 0 | 0
09-Feb-2018 | 0 | 0
10-Feb-2018 | 23 | 1
Thank you in advanced.

Typo3 TCA custom table

I have this situation, I have one offer, and that offer have n number of dates, and n number of options. So I have two additional tables for offer. And third one, which is a price, but price depends of date, and offer. And it is like this:
| | date 1 | date 2 | date 3 |
| offer 1 | price 11 | price 12 | price 13 |
| offer 2 | price 21 | price 22 | price 23 |
| offer 3 | price 31 | price 32 | price 33 |
Is there any way to create TCA custom field to insert all of this Price values at once?
So, basically I need one table with input fields and to store also uid of date and offer in it as reference.
Make more than one table... Tables with dynamic col count are horrible bad to maintain.
Table Offer:
uid | Name | Desc
1 | offer1 | This is some cool shit
2 | offer2 | dsadsad
3 | offer3 | sdadsdsadsada
Table Date:
uid | date
1 | 12.02.2014
2 | 12.03.2014
3 | 20.03.2014
Table Prices:
uid | date | offer | price
1 | 1 | 1 | price11
2 | 1 | 2 | price21
3 | 1 | 3 | price31
4 | 2 | 1 | price12
5 | 2 | 2 | price22
6 | 2 | 3 | price32
7 | 3 | 1 | price13
8 | 3 | 2 | price23
9 | 3 | 3 | price33
And then its straight forward...

Summing columns in a row in all rows with Emacs org-mode

I'm using Emacs org-mode to track times worked on various tasks. The last column in the table is the weekly sum for each task:
|------+-----+-----+-----+-----+-----+-------|
| Task | Mon | Tue | Wed | Thu | Fri | Total |
|------+-----+-----+-----+-----+-----+-------|
| Foo | 2 | 3 | 4 | 5 | 6 | 20 |
| Bar | 2 | 3 | 4 | 5 | 7 | 21 |
#+TBLFM: #2$7=vsum($2..$6)::#3$7=vsum($2..$6)
Currently, I have to add a formula for each new row. Is there any way to customise the formula so that it calculates the sums regardless of how many rows there are?
Column formula did the trick as suggested by fniessen. Here's what I ended up with:
|------+-----+-----+-----+-----+-----+-------|
| Task | Mon | Tue | Wed | Thu | Fri | Total |
|------+-----+-----+-----+-----+-----+-------|
| Foo | 2 | 3 | 4 | 5 | 6 | 20 |
| Bar | 2 | 3 | 4 | 5 | 7 | 21 |
#+TBLFM: $7=vsum($2..$6)
More info in the Column formulas and field formulas section from the docs.
You really should take a closer look at the documentation, and read about "column formulas" (and, even, "row formulas"). A colum formula is $7=...' and is editable viaC-c ='.