How do I display a tree view based on this given database data? - sql

The table looks like:
id | title | parent | depth |
---+-------+--------+-------+
1 | blah | 0 | 0
---+-------+--------+-------+
2 | blah | 0 | 0
---+-------+--------+-------+
3 | blah | 0 | 0
---+-------+--------+-------+
4 | blah | 2 | 1
---+-------+--------+-------+
5 | blah | 2 | 1
---+-------+--------+-------+
6 | blah | 5 | 2
---+-------+--------+-------+
I want to take that data and output it into a tree like view. Similar to:
1 - blah
2 - blah
4 - blah
5 - blah
6 - blah
3 - blah
Someone suggested I use the query:
SELECT title, depth FROM table ORDER BY parent, id
I could then use the depth to create the whitespace on the left and format the tree. This works up until I use HTML. I want to be able to format it nicely in valid HTML and then style it with CSS, etc...
Using just the depth, I can't think of a way to wrap the comments in a div class="parent/child" type structure.
How can I format the data?

Use a <ul> in HTML, with a <li> for each item. Every time you increase in depth compared to the last item, add one <ul> to the current <li> instead of closing it. If the current depth is lower than the previous, close off one </ul></li> pair for each level of depth difference.

if you already have figured out how to get the depth of an entry (or the number of ancestors that is), then you could try the following:
css code:
.tab {
margin-left: 20px;
}
rendered html code:
<p>
<span class="">1 - blah</span><br />
<span class="">2 - blah</span><br />
<span class="tab">4 - blah</span><br />
<span class="tab">5 - blah</span><br />
<span class="tab tab">6 - blah</span><br />
<span class="">3 - blah</span>
</p>
and you'll use your logic to determine how many "tab" to add to the span's class attribute. each "tab" you add puts that line 20 more pixels to the right.

Related

Weighted + ordered tag search using Postgres

After an AI file analysis across tens of thousands of audio files I end up with this kind of data structure in a Postgres DB:
id | name | tag_1 | tag_2 | tag_3 | tag_4 | tag_5
1 | first song | rock | pop | 80s | female singer | classic rock
2 | second song | pop | rock | jazz | electronic | new wave
3 | third song | rock | funk | rnb | 80s | rnb
Tag positions are really important: the more "to the left", the more prominent it is in the song. The number of tags is also finite (50 tags) and the AI always returns 5 of them for every song, no null values expected.
On the other hand, this is what I have to query:
{"rock" => 15, "pop" => 10, "soul" => 3}
The key is a Tag name and the value an arbitrary weight. Numbers of entries could be random from 1 to 50.
According to the example dataset, in this case it should return [1, 3, 2]
I'm also open for data restructuring if it could be easier to achieve using raw concatenated strings but... is it something doable using Postgres (tsvectors?) or do I really have to use something like Elasticsearch for this?
After a lot of trials and errors this is what I ended up with, using only Postgres:
Turn all data set to integers, so it moves on to something like this (I also added columns to match the real data set more closely) :
id | bpm | tag_1 | tag_2 | tag_3 | tag_4 | tag_5
1 | 114 | 1 | 2 | 3 | 4 | 5
2 | 102 | 2 | 1 | 6 | 7 | 8
3 | 110 | 1 | 9 | 10 | 3 | 12
Store requests in an array as strings (note that I sanitized those requests before with some kind of "request builder"):
requests = [
"bpm BETWEEN 110 AND 124
AND tag_1 = 1
AND tag_2 = 2
AND tag_3 = 3
AND tag_4 = 4
AND tag_5 = 5",
"bpm BETWEEN 110 AND 124
AND tag_1 = 1
AND tag_2 = 2
AND tag_3 = 3
AND tag_4 = 4
AND tag_5 IN (1, 3, 5)",
"bpm BETWEEN 110 AND 124
AND tag_1 = 1
AND tag_2 = 2
AND tag_3 = 3
AND tag_4 IN (1, 3, 5),
AND tag_5 IN (1, 3, 5)",
....
]
Simply loop in the requests array, from the most precise to the most approximate one:
# Ruby / ActiveRecord example
track_ids = []
requests.each do |request|
track_ids += Track.where([
"(#{request})
AND tracks.id NOT IN ?", track_ids
]).pluck(:id)
break if track_ids.length > 200
end
... and done! All my songs are ordered by similarity, the closest match at the top, and the more to the bottom, the more approximate they get. Since everything is about integers, it's pretty fast (fast enough on a 100K rows dataset), and the output looks like pure magic. Bonus point: it is still easily tweakable and maintainable by the whole team.
I do understand that's rough, so I'm open to any more efficient way to do the same thing, even if something else is needed in the stack (ES ?), but so far: it's a simple solution that just works.

Oracle SQL - Give each row in a result set a unique identifier depending on a value in a column

I have a result set, being returned from a view, that returns a list of items and the country they originated from, an example would be:
ID | Description | Country_Name
------------------------------------
1 | Item 1 | United Kingdom
2 | Item 2 | France
3 | Item 3 | United Kingdom
4 | Item 4 | France
5 | Item 5 | France
6 | Item 6 | Germany
I wanted to query this data, returning all columns (There are more columns than ID, Description and Country_Name, I've omitted them for brevity's sake) with an extra one added on giving a unique value depending on the value that is inside the field Country_name
ID | Description | Country_Name | Country_Relation
---------------------------------------------------------
1 | Item 1 | United Kingdom | 1
2 | Item 2 | France | 2
3 | Item 3 | United Kingdom | 1
4 | Item 4 | France | 2
5 | Item 5 | France | 2
6 | Item 6 | Germany | 3
The reason behind this, is we're using a Jasper report and need to show these items with an asterisk next to it (Or in this case a number) explaining some details about the country. So the report would look like this:
Desc. Country
Item 1 United Kingdom(1)
Item 2 France(2)
Item 3 United Kingdom(1)
Item 4 France(2)
Item 5 France(2)
Item 6 Germany(3)
And then further down the report would be a field stating:
1: Here are some details about the UK
2: Here are some details about France
3: Here are some details about Germany
I'm having difficulty trying to generate a unique number to go along side each country, starting at one each time the report is ran, incrementing it when a new country is found and keeping track of where to assign it. I would hazard a guess at using temporary tables to do such a thing, but I feel that's overkill.
Question
Is this kind of thing possible in Oracle SQL or am I attempting to do something that is rather large and cumbersome?
Are there better ways of doing this inside of a Jasper report?
At the moment, I'm looking at just having the subtext underneath each individual item and repeating the same information several times, just to avoid this situation, rather than having them aggregated and having the subtext once. It's not clean, but it saves this rather odd hassle.
You are looking for dense_rank():
select t.*, dense_rank() over (order by country_name) as country_relation
from t;
I don't know if this can be done inside Jasper reports. However, it is easy enough to set up a view to handle this in Oracle.

Database Table: Quantity or redundancy

I'm building a database which have a lot of items for a bike shop. This bike shop have many of the same items such as 100 wheels of size 4 and color 'red'. My question is:
Is is better to add a 'Quantity' field to the entity set and put all similar items in one entity (example 1) or is it better to have an entity for each item (example 2)?
Example 1:
id | color | size | quantity
1 | red | 4 | 100
Example 2:
id | color | size
1 | red | 4
2 | red | 4
3 | red | 4
etc.
The first - qqhantity field - unless you have a reason to track for example serial numbers, and even then you may go to v1 and use a separate column.
Generally: get a copy of the Data Model Ressoure Book Vol 1 - it has a ton of discussions about standard business data problems, among them an inventory system. You will learn a lot.

parse multiline varchar field into rows (T-sql)

I am making a report in SSRS. Database contains table "Project" with a "Notes" field which is formated by users in this way:
#Completed
-line 1 description
-line 2 description
-line3 and so on
#Planned
-line 1 etc.
#Risks
- line1 ...etc
There are always only those 3 categories and in that order. Bullet points can be from 0 to unlimited (but i never seen more than 10)
I would like to get output(dataset) in format (so I can group them in tablix):
ProjectID, Maincategory, itemID, subcategories.
For example
1 | Completed | 1 | line1
1 | Completed | 2 | line2
1 | Completed | 3 | line3
...
1 | Planned | 1 | Line1
...
1 | Risks | 1 | line1
...
I cant change source DB so I cant create stored procedure, it should be regular query.
I looked at various solutions with CTE recursions but I just cant figure out how they work in oreder to change them for my case.
Thank you!

In textile, how do I set the class of an (un)ordered list?

Using textile, I can set the class of a table by writing
table(myClass).
| a | b | c |
produces
<table class="myClass">
...
But how can I do the same thing for (un)ordered lists?
# Item 1
# Item 2
# Item 3
to make textile product
<ol class="myClass">
<li>...