Hierarchical Filtering in tableau - tableau-api

I have a filter that includes cities and I have another filed that is region and each city goes with a region. For example:
New York -> RegionID = 1
Seattle -> RegionID = 2
Boston -> RegionID = 2
Nashville -> RegionID = 3
Now I want to filter my sheets and dashboard with cities but I want this to be hierarchy that user can select RegionID and Cities corresponding with that reagion appears to select from.
How can I do such thing?

Tableau can do this with "Values from Hierarchy" in the filter options. In fact, this is the default behavior now. https://help.tableau.com/current/pro/desktop/en-us/filtering.htm#set-options-for-filter-card-interaction-and-appearance
There is also an Extension that can display this in a tree view. https://github.com/tableau/extension-hierarchy-navigator-sandboxed

Related

Accessing the ATTR field troubleshooting in Tableau?

I am working on Tableau server but I believe the problem I am facing does not correspond to tableau server specifically.
I am using two data sources ds1 and ds2 which are joined using the dimension Id . ds1 has a field city and ds2 has a field district. There is only 1 city corresponding to each Id but there can be multiple district corresponding to an Id .
I have created a calculated field Points in ds2 which is described in the code segment.
I have researched from different sites and blogs (including tableau support). I came to a close possible reason behind this and I might be wrong . The ATTR function which works on row level and identify if a row is unique then it outputs the dimension otherwise it outputs '*' . I think when I joined those two tables the district dimension in ds2 might have the '*' instead of actual district values, so it might not be able to compare the conditions in if statements of Point .
//Point//
IF [city] == "Delhi"
AND [district] == "Dist1"
AND [district] == "Dist2"
THEN "100 Section"
ELSEIF [city] == "Mumbai"
AND [district] == "Dist11"
AND [district] == "Dist12"
THEN "200 Section"
ELSE "Other Section"
END
When I insert data which satisfy the conditions in calculated field, it is going in Other section of the Point .I want it to go in desired section.
For instance
Id = 19
city = Delhi
district = Dist1
district = Dist2
district = Dist3
It should go in 100 Section but it is going in Other Section . What modifications should I do or add to make the Point work properly ?

libreoffice base create a list filtered by another list's value

I have a table of provinces and a table of cities with ProvienceID. In a form, I want to create a list of cities filtered by selected value of provience list.
How can I do that?
I can create both lists but Cities list shows all cities from all provinces but i want to show only cities from the province that I have selected in Provinces list.
I have another table "Users" with "CityID" and "ProvinceID" that my form edits it and I need to save selected values of Province and City Lists in it, not only show it in the form.
Create two example tables named "Provinces" and "Cities".
ProvinceID Name
~~~~~~~~~~ ~~~~
0 South
1 North
2 Large Midwest
3 Southeast
4 West
CityID Name ProvinceID
~~~~~~ ~~~~ ~~~~~~~~~~
0 Big City 2
1 Very Big City 2
2 Rural Village 1
3 Mountain Heights 0
4 Coastal Plains 4
5 Metropolis 2
Create a query called "ProvinceNames":
SELECT "Name" AS "Province"
FROM "Provinces"
ORDER BY "Province" ASC
Create a query called "Province of City":
SELECT "Provinces"."Name" AS "Province", "Cities"."Name" AS "City"
FROM "Cities", "Provinces" WHERE "Cities"."ProvinceID" = "Provinces"."ProvinceID"
ORDER BY "Province" ASC, "City" ASC
In the form, create a table control based on the query "ProvinceNames".
Using the Form Navigator (or the Form Wizard), create a subform for query "Province of City".
Right-click on subform and choose Properties. Under Data tab:
Link master fields "Province"
Link slave fields "Province"
Create a table control for the subform as well. Now, the cities shown in the subform control depend on the province selected in the main form control.
EDIT:
Here is an example using a filter table to store the current value of the list box. Create two more tables named "Users" and "FilterCriteria".
UserID Name ProvinceID CityID
~~~~~~ ~~~~~~~ ~~~~~~~~~~ ~~~~~~
0 Person1 1 2
1 Person2 2 0
RecordID ProvinceID CityID
~~~~~~~~ ~~~~~~~~~~ ~~~~~~
the only 0 0
We'll also need two Basic macros which can be stored in the document or in My Macros. Go to Tools -> Macros -> Organize Macros -> LibreOffice Basic.
Sub ReadProvince (oEvent as Object)
forms = ThisComponent.getDrawPage().getForms()
mainForm = forms.getByName("MainForm")
cityForm = forms.getByName("CityForm")
listboxProvince = mainForm.getByName("listboxProvince")
listboxCity = cityForm.getByName("listboxCity")
selectedItemID = listboxProvince.SelectedValue
If IsEmpty(selectedItemID) Then
selectedItemID = 0
End If
conn = mainForm.ActiveConnection
stmt = conn.createStatement()
strSQL = "UPDATE ""FilterCriteria"" SET ""ProvinceID"" = " & selectedItemID & _
"WHERE ""RecordID"" = 'the only'"
stmt.executeUpdate(strSQL)
listboxCity.refresh()
lCityCol = mainForm.findColumn("CityID")
currentCityID = mainForm.getInt(lCityCol)
cityForm.updateInt(cityForm.findColumn("CityID"), currentCityID)
listboxCity.refresh()
End Sub
Sub CityChanged (oEvent as Object)
listboxCity = oEvent.Source.Model
cityForm = listboxCity.getParent()
mainForm = cityForm.getParent().getByName("MainForm")
lCityCol = mainForm.findColumn("CityID")
selectedItemID = listboxCity.SelectedValue
If IsEmpty(selectedItemID) Then
selectedItemID = 0
End If
mainForm.updateInt(lCityCol, selectedItemID)
End Sub
Now we need to set up the form like this. In this example, I used two top-level forms instead of a subform. ProvinceID and CityID text boxes are not required but may be helpful in case something goes wrong.
To start creating this form, use the form wizard to create a new form and add all fields from the Users table.
Now, in the Form Navigator, create a form called "CityForm". Content type is SQL command, and Content is:
SELECT "RecordID", "ProvinceID", "CityID" FROM "FilterCriteria"
WHERE "RecordID" = 'the only'
Next, create the "listboxProvince" list box under MainForm. Data Field is "ProvinceID", and List content is the following Sql.
SELECT "Name", "ProvinceID" FROM "Provinces" ORDER BY "Name" ASC
Finally, create the "listboxCity" list box under CityForm. Data Field is "CityID", and List content is the following Sql.
SELECT "Name", "CityID" FROM "Cities" WHERE "ProvinceID" = (
SELECT "ProvinceID" FROM "FilterCriteria"
WHERE "RecordID" = 'the only')
Macros are linked under the Events tab of each control.
Assign "After record change" of the MainForm to ReadProvince().
Assign "Changed" of listboxProvince to ReadProvince().
Assign "Changed" of listboxCity control to CityChanged().
The result allows us to select the Province to filter the list of Cities. Provinces and Cities that are selected are saved in the Users table.
There is another approach which may be better that I have not had time to explore. Instead of the "FilterCriteria" table, apply a filter to the Cities list. The relevant code in ReadProvince() would look something like this.
cityForm.Filter = "ProvinceID=" & selectedItemID
cityForm.ApplyFilter = True
cityForm.reload()
cityForm.absolute(0)
Whatever approach is taken, a complete solution requires complex macro programming. To make it easier, you may decide to use a simpler solution that is not as powerful. For more information, there is a tutorial at https://forum.openoffice.org/en/forum/viewtopic.php?t=46470.
EDIT 2
A solution that requires fewer queries is at https://ask.libreoffice.org/en/question/143186/how-to-use-user-selected-value-from-combobox1-in-combobox2-select-statement/?answer=143231#post-id-143231. The second list box is based on a list of values instead of an SQL query.

Reshaping data in a postgres query?

I have two tables in CartoDB, one of community district polygons, and one of sites that are in those community districts.
I know the district (borocd) of each site, so I can get a list of counts of sites of each type with:
SELECT borocd, type, count(*) FROM sites GROUP BY borocd, type
But I'm having a hard time wrapping my head around how I'd update my "districts" table with columns for count of type1 and count of type2 in a single query. I wound up doing this:
UPDATE districts
SET type1_sites = (
SELECT count(*) FROM sites
WHERE type='type1' AND districts.borocd = sites.borocd
GROUP BY borocd
)
And repeating that for type 2. But could I have done that more cleanly?
UPDATE districts
SET type1_sites = (
SELECT count(*) FROM sites WHERE type='type1' AND districts.borocd = sites.borocd
),
type2_sites = (
SELECT count(*) FROM sites WHERE type='type2' AND districts.borocd = sites.borocd
);
Assuming you have separate columns for type1 and type2.

Adding Columns heading to report if no data in a given period

I have a dataset for each record it has a CompanyID, RevenueMonth, RevenueYear, Revenue
When I create the report, I am grouping each CompanyID and showing their monthly revenue for a given year.
But in a given year, not all companies have any revenues for a particular month.
Example:
A sample record would look like:
CompanyID, RevenueMonth, RevenueYear, Revenue
1,05,2013,5.00
1,08,2013,6.00
1,03,2013,3.00
End Result, I would like my report to look like this with CompanyID 1.
Company ID|01|02|03|04|05|06|07|08|09|10|11|12
1 0.00|0.00|3.00|0.00|5.00|0.00|0.00|6.00|0.00|0.00|0.00|0.00
In my current Report, it will only fill column headings with March (03), May (05) and August (08).
Company ID|03|05|08
1 3.00|5.00|6.00
How do I get my Report to add the missing months for the year?
I hope my questions is clear.
Database level
Since you're only returning a year at a time, you can create a calendar table and add this to your result set:
Keeping it as simple as possible, with the date table coming from a CTE:
with months as -- get required year/months
(
select RevenueYear = 2013
, RevenueMonth = 1
union all
select RevenueYear = 2013
, RevenueMonth = RevenueMonth + 1
from months
where RevenueMonth < 12
)
select CompanyID = coalesce(r.CompanyID, c.companyID)
, RevenueMonth = coalesce(r.RevenueMonth, m.RevenueMonth)
, RevenueYear = coalesce(r.RevenueYear, m.RevenueYear)
, Revenue = isnull(r.Revenue, 0.0)
from months m
cross join (select distinct CompanyID from records) c -- make sure all companies included
left join records r on m.RevenueYear = r.RevenueYear
and m.RevenueMonth = r.RevenueMonth
SQL Fiddle with demo.
This will return a year/month for each company in the result set.
In the long run it would be better to move from a CTE to a permanent calendar table in the database.
You can then implement this in the report using a matrix style tablix.
Report level
If you'd prefer to do this at the report level, you can set up a table-style tablix with 12 permanent columns, one for each month, then populate the month revenue cells with expressions like:
=Sum(IIf(Fields!RevenueMonth.Value = 2, Fields!Revenue.Value, Nothing)
For the February column.
This would work with your existing dataset without any database code changes.

simple LINQ query

i am having trouble joinging tables on a LINQ query.
(source: kalleload.net)
As you can see there are three tables there. On my webpage, i want to display the following data in a List View.
betid | bet.title | bet.description | match.location | match.begindate/enddate | teamone NAME | teamtwo Name.
so let me explain this.
I want 3 fields from the bets table.
I want 2 fields from the match table (where the match.matchid = bet.matchid)
I want 2 fields from the TEAM table (where match.teamone = team.teamid and match.teamtwo = team.teamid)
i hope this makes sense.
thankyou
It looks like you already have the relationships defined. If you are using the designer, you should have existing entities in the generated classes.
var result = bet.Select( b => new {
BetID = b.betid,
Title = b.title,
Description = b.description,
BeginDate = b.match.begindate,
EndDate = b.match.enddate,
TeamOneName = b.match.team_1.teamname,
TeamTwoName = b.match.team_2.teamname
} );
Note that I'm only guessing at the association names. You should be able to figure out the names given to them by the designer.
The key to this one is to include a self join on the team table, for team one and team two, like this:
var result = from bet in db.bet
join match in db.match on bet.matchid equals match.matchid
join team1 in db.team on match.teamone equals team1.teamid
join team2 in db.team on match.teamtwo equals team2.teamid
select new {bet.betid, bet.title, bet.description, match.location, match.begindate, match.enddate, team1.name, team2.name};