Database relationships - 1:1 but not always? - database

Apologies for the fairly unhelpful title, if you have a better suggestion please feel free to edit it.
I'm using CakePHP and the bake functionality (I don't need to bake however).
What's the best way of achieving the following:
table schema:
table ranges
id | name | description
table images
id | range_id | picture
table info (here i am confused)
id | range_id | height | width | colour
Basically, one range may have many images (1:Many). I can show this fine.
Now, each range will have an entry in the info table (1:1) and some attributes about the range such as height, colour, width. But not always...
Let's say I have a range foo. foo has five images that all have the same height, width and colour. However, foo has one image that is a different size and a different colour.
When the attributes differ, I need to show this information with the respective image, rather than the ranges default information. So this image will need it's own entry in the info table.
Does this even make sense? Or am I going about this entirely the wrong way.
My application, in brief:
(If it helps, think of "range" as a product)
User selects a range
User views images in the range
User can click an image, and the information from info pops up about that range.
Some images have different attributes, but still belong to the same range.
How can I make this distinction and store it appropriately?
Please let me know if I can clarify further. Thank you.

I've needed to do this on occasion where a parent entity has a value that can get "overridden" by a child entity.
There are a couple of approaches you can take the structure being the easiest part.
consider the following structure
table ranges
id | name | description | default_info_id
table images
id | range_id | picture | info_id
table info
id | height | width | colour
When does image.info_id have a value? There are two choices
Populate the image.info_id with the default_info_id from the parent. The user can then override it on the image
Pros
You never need to look at the Range to figure out what the info is on the image
Cons
you need to decide what to do when the range.default_info_id changes. does it effect the images or is it just for future
Only Populate the images.info_id when its different than the parent.
Pros
If the parents.default_info_id changes when images.info_id is null it will automatically change as well
Cons
you need to decide what to do when the range.default_info_id changes. Do you need to now null out any images.info_id that are now the same as the parent?
You need to look at the rages table to figure out what the info_id is on the images when its null.
You can have several varieties of the above data structures but you'll still need to figure when to populate what. Here are two others you could consider that are valid (but less optimal in my opinion)
Info has an FK to both tables but one is always null
table ranges
id | name | description
table images
id | range_id | picture
table info
id | range_id | image_id | height | width | colour
No Info Table at all
table ranges
id | name | description | default_height | default_width | default_colour
table images
id | range_id | picture | height | width | colour

Related

Is it possible to create a repeating table in SSRS Report based on data from SQL database?

I have created a Powerapp which is used to audit schools and the data saves to my SQL database. I have designed a report in SSRS to display the findings of the audit. The SQL table, shown below, stores the items in each room that were audited (i.e. desks, pcs, shelves etc) plus the name of the room and whether any actions need to take place. I need my report to display one table per room with the items down the left hand side and the name of the room as a title. This should be repeated for each room. There may be a different number of rooms in each report so this will be varied. I've included a screenshot of what the table needs to look like. When I create the table, I can only get the room names down the left hand side in one table and the items across the top. Please help.
Too long for a comment so I'll have to reply here.
Your data is not a a format that is particularly suited to this. I can't see how you can determine 'Compliant' from the data you have shown in your screen shots although it maybe that you have not shown everything you have available.
However, I would start by looking into the t-sql UNPIVOT function to get your data into a more normalised format. Using UNPIVOT you could turn your data into something like..
AuditID | Room | Item | Present
------------------------------------------
3019 | Reception | PC | True
3019 | Reception | Desks | True
3019 | Class 1 | PC | False
3019 | Class 1 | Desks | True
You can obviously extend this to include all pertinent data.
Once you have your data in this format, create tablix with 'item' and 'present' columns only. You will have a 'detail' rowgroup at this point. Right-click the rowgroup and add a parent group, set this group to be grouped by Room.
This will give you the basic layout, from there you can add some padding or blank rows to the room group or even page breaks.
If you cannot get past the UNPIVOT function then I suggest you post a new question specifically on that topic then return here once you have the data in the correct format

Different choices for inputting text into database

I am making a database of images. Each image has a certain amount of Chinese text in it. When I have made the database, I want to be able to search the text and find the image it is attached to, and vice-versa.
In each image, the largest and highest-up-the-page text is the "main text", and the rest are "secondary text". In a few images, the amount of discrete secondary texts is high (>10 pieces). The images' text varies quite a lot, so the chances that one image will have the same text as another are small. See an example image (below) where there is one main text (某词), and three secondary texts (战略, 微笑, 容易).
My question is: Should I have two columns in my "images" table, where the first column is "main text" and the other column is "secondary text", containing all other text in the image? Or should I have multiple columns allowing for X number of discrete secondary texts? I have so far assumed that it would be relatively meaningless to create a "text" table and connect it with the images table via an associative table, since the majority of the texts are unique.
A problem: Because the images I am looking at largely do not use punctuation, and Chinese characters are not written with spaces between them, having one column for all "secondary text" could very easily lead to query confusions. For example, if I take all three pieces secondary text in the example image (战略, 微笑 and 容易) and concatenate them, it becomes 战略微笑容易. But now, this has become a text containing potentially five words: 战略, 略微, 微笑, 笑容, 容易. This would create chaos in my queries.
The cleanest way would probably be to create a separate table for (at least secondary) texts. If they are largely unique you can do this without an association table.
Table images:
ID | image | main text
---+-------+----------
1 | <img> | 某词
Table secondary:
ID | image_id | secondary text
---+----------+---------------
1 | 1 | 战略
2 | 1 | 微笑
3 | 1 | 容易
If it fits your use case better, you could also put all your texts along with their type into the second table:
Table images:
ID | image
---+-------
1 | <img>
Table text:
ID | image_id | text | type
---+----------+------+----------
1 | 1 | 战略 | 2
2 | 1 | 微笑 | 2
3 | 1 | 容易 | 2
4 | 1 | 某词 | 1

Load big table into web browser using react in on-demand instantiation of table row

I'm building a Excel-like table into web browser with React.js using only <div> not <table>.
Number of columns are about 90, rows are about 24000.
As we know, it is impossible to load whole data into HTML at single web page due to performance issue.
So I decided to show partial data to user using scrolling.
The main concept is simple, build HTML near user's viewport.
Guess if user is seeing 1800th to 1900th data in single viewport. I'will load only about 1750th ~ 1950th data into HTML. If user scroll up, I'll load HTML for 1700th ~ 1750th data and remove 1900th ~ 1950th data.
I think I need to manually manipulate scroll offset for getting pos where user is at. If each row's height is same as 40px and height of viewport is 1000px, then user will see 25 items at single viewport, so I need to load about 25(front) + 25(currently seeing) + 25(end) data and if user go upside or downside, I'll load additional data and remove data which far away from user.
However, I found that, requirement for my table is not matched with this situations. Here's my situation.
First, Each row's height is not same. Basically my table will show rows of row as single row. What I mean is, table single row can be looks like below,
| Photo| ProductName | Size Pool | Stock |
.... // Below are single row
+------+---------------+-------------------+------------+
| | Boots | 110-120 | 24 | // Row header (Shows Summary of child row)
+ +---------------+-------------------+------------+
| | Boots | 110 | 16 | // Row's row #1
+ +---------------+-------------------+------------+
| | Boots | 120 | 8 | // Row's row #2
+------+------------------------------------------------+
...
+------+---------------+-------------------+------------+
| |Leather Shoe | 120 | 8 | // Row can come with no header row, only single
+------+---------------+-------------------+------------+
...
Like above, if product has more than 2 options, then it merge into rows of single row and show with summary header. And if not a option product, it shows only it's row. And if content inside the row is big, it will stretch to fit the content inside
All data came from remote DataBase which retrieve data via REST API.
DataBase scheme is like below, 2 table as example.
Table #1 ProductInfo
+--------------+------------+------------+-----------+
| GroupNumber |ProductName | Size | Stock |
+--------------+------------+------------+-----------+
| 1 | Boots | 110 | 16 |
+--------------+------------+------------+-----------+
| 1 | Boots | 120 | 8 |
+--------------+------------+------------+-----------+
| 2 |Leather Shoe| 120 | 8 |
+--------------+------------+------------+-----------+
Table #2 GroupInfo
+-----------+------------+--------------+
|GroupNumber| SizePool | ImageURL |
+-----------+------------+--------------+
| 1 | 110-120 | https://abc |
+-----------+------------+--------------+
| 2 | 120 | https://def |
+-----------+------------+--------------+
And future requirements are below, (And most of them are implemented)
Sort by each columns, multi-pivot sort by row of row OR row (Handled via SQL)
Filter data by expression (Handled by client)
Hiding, resizing, change order of column(s) (Handled by client)
Interactable component inside cell like DatePicker, Pop-up etc... (Handled by client)
I succeed to create such table with page based method. But I need scrolling viewport table.
The table contains lots of dependent value column like sum, average which are not in stored in DB except for special reason (Like performance). (Most of them are handled by DB View or Procedure including sorting, calculations etc). So overall performance is really important.
I considered few questions and way to handle this, Can you check and give me a advice?
Q1. How can I decide when data should be loaded and removed and it's amount?
Data height is not consistent, so I think I cannot use scroll offset or data number as measurement criteria. (Is it possible with predictable way?)
Is it possible to archive by accessing DOM element? I'm new to Web dev. Sorry.
Q2. I can get a data from DB in 2 different ways.
Getting ProductInfo And GroupInfo seperately [<ProductInfo>,...] And [<GroupInfo>,...]
Getting Single group which object like this { group:<GroupINfo>, values:[<ProductInfo>,...] }
which is better for performance in this case in typical situations?
Q3. If I got a data like { group:<GroupINfo>, values:[<ProductInfo>,...] }, is there any problems with performance?
Like query overhead (I need to use query joined 6 times with maximum 6 depth nested SELECT query with 30 calculated columns for single data retrieval attempt. -- Pre-calculated view or table can have problems because I have many user to use it and update frequently. So I need to worry about Mutual Exclusive at least on updating.
I'm sure that above query's performance is sufficient for cropping if I got data like [<ProductInfo>,...] And [<GroupInfo>,...]. But I think later one is better. so I need to change interface if possible.
Q4. If I crop whole data from DB and structurize at the beginning, and load and remove data only for DOM, Can it be a good way?
Of course, Q1 is my primary matter, but this also seems good except for data sync with DB (Cause other user can update value while client contain outdated data)
I considered of using Infinite-Scrolling, but this is not for my case, I need perform load data and remove data at the same time. But infinite-scrolling seems dose not support removing data from viewport. Also inconsistent row height may be a problem.
I found react-virtualized and it works.
It also support dynamic resizing of row and it greatly helped

Normalizing a Table 6

I'm putting together a database that I need to normalize and I've run into an issue that I don't really know how to handle.
I've put together a simplified example of my problem to illustrate it:
Item ID___Mass___Procurement__Currency__________Amount
0__________2kg___inherited____null________________null
1_________13kg___bought_______US dollars_________47.20
2__________5kg___bought_______British Pounds______3.10
3_________11kg___inherited____null________________null
4__________9kg___bought_______US dollars__________1.32
(My apologies for the awkward table; new users aren't allowed to paste images)
In the table above I have a property (Amount) which is functionally dependent on the Item ID (I think), but which does not exist for every Item ID (since inherited items have no monetary cost). I'm relatively new to databases, but I can't find a similar issue to this addressed in any beginner tutorials or literature. Any help would be appreciated.
I would just create two new tables ItemProcurement and Currencies.
If I'm not wrong, as per the data presented, the amount is part of the procurement of the item itself (when the item has not been inherited), for that reason I would group the Amount and CurrencyID fields in the new entity ItemProcurement.
As you can see, an inherited item wouldn't have an entry in the ItemProcurement table.
Concerning the main Item table, if you expect just two different values for the kind of procurement, then I would use a char(1) column (varying from B => bougth, I => inherited).
I would looks like this:
The data would then look like this:
TABLE Items
+-------+-------+--------------------+
| ID | Mass | ProcurementMethod |
|-------+-------+--------------------+
| 0 | 2 | I |
+-------+-------+--------------------+
| 1 | 13 | B |
+-------+-------+--------------------+
| 2 | 5 | B |
+-------+-------+--------------------+
TABLE ItemProcurement
+--------+-------------+------------+
| ItemID | CurrencyID | Amount |
|--------+-------------+------------+
| 1 | 840 | 47.20 |
+--------+-------------+------------+
| 2 | 826 | 3.10 |
+--------+-------------+------------+
TABLE Currencies
+------------+---------+-----------------+
| CurrencyID | ISOCode | Description |
|------------+---------+-----------------+
| 840 | USD | US dollars |
+------------+---------+-----------------+
| 826 | GBP | British Pounds |
+------------+---------+-----------------+
Not only Amount, everything is dependent on ItemID, as this seems to be a candidate key.
The dependence you have is that Currency and Amount are NULL (I guess this means Unknown/Invalid) when the Procurement is 'inherited' (or 0 cost as pointed by #XIVsolutions and as you mention "inherited items have no monetary cost")
In other words, iems are divided into two types (of procurements) and items of one of the two types do not have all attributes.
This can be solved with a supertype/subtype split. You have a supertype table (Item) and two subtype tables (ItemBought and ItemInherited), where each one of them has a 1::0..1 relationship with the supertype table. The attributes common to all items will be in the supertype table and every other attribute in the respecting subtype table:
Item
----------------------------
ItemID Mass Procurement
0 2kg inherited
1 13kg bought
2 5kg bought
3 11kg inherited
4 9kg bought
ItemBought
---------------------------------
ItemID Currency Amount
1 US dollars 47.20
2 British Pounds 3.10
4 US dollars 1.32
ItemInherited
-------------
ItemID
0
3
If there is no attribute that only inherited items have, you even skip the ItemInherited table altogether.
For other questions relating to this pattern, look up the tag: Class-Table-Inheritance. While you're at it, look up Shared-Primary-Key as well. For a more concpetual treatment, google on "ER Specialization".
Here is my off-the-cuff suggestion:
UPDATE: Mass would be a Float/Decimal/Double depending upon your Db, Cost would be whatever the optimal type is for handling money (in SQL Server 2008, it is "Money" but these things vary).
ANOTHER UPDATE: The cost of an inherited item should be zero, not null (and in fact, there sometime IS an indirect cost, in the form of taxes, but I digress . . .). Therefore, your Item Table should require a value for cost, even if that cost is zero. It should not be null.
Let me know if you have questions . . .
Why do you need to normalise it?
I can see some data integrity challenges, but no obvious structural problems.
The implicit dependency between "procurement" and the presence or not of the value/currency is tricky, but has nothing to do with the keys and so is not a big deal, practically.
If we are to be purists (e.g. this is for homework purposes), then we are dealing with two types of item, inherited items and bought items. Since they are not the same type of thing, they should be modelled as two separate entities i.e. InheritedItem and BoughtItem, with only the columns they need.
In order to get a combined view of all items (e.g. to get a total weight), you would use a view, or a UNION sql query.
If we are looking to object model in the database, then we can factor out the common supertype (Item), and model the subtypes (InheritedItem, BoughtItem) with foreign-keys to the supertype table (ypercube explanation below is very good), but this is very complicated and less future-proof than only modelling the subtypes.
This last point is the subject of much argument, but practically, in my experience, modelling concrete supertypes in the database leads to more pain later than leaving them abstract. Okay, that's probably waaay beyond what you wanted :).

database structure for static pages

please help me on this one:)
Most of the time I am creating static pages like Contact Us, About Us, FAQs etc
If I want to store some dynamic items in the page, how will my table look like?
Let's say for the FAQ page, I am to store the question and the answer on the database. For the contact page, I will store emails and and some other contact information. Does that mean I have to create a separate table for each?
Often times I've seen people create a table for Meta information. It resembles a key => value relationship, where the first field of a row is the name and the second is the value. So if you were to manage your global contact information in the database, you may have the following rows:
Meta-Data Table
Meta ID | MetaTitle | Meta Value
---------------------------------------------------------
01 | email_address | some.guy#somedomain.com
02 | phone_number | 1.234.567.8901
03 | num_subscribers | 2312
04 | page_styles | background-color:#333333;color:#ffffff
As for your frequently asked questions, you could do that as a table, if you like:
Questions
Question ID | Question | Answer
-------------------------------------------
01 | How tall are you? | Not nearly tall enough.
Or you could simply create a generic 'pages' table:
Pages
Page ID | Page Title | Page Content
--------------------------------------------
01 | FAQs | How tall are you?
| | Not nearly tall enough.
--------------------------------------------
02 | Contact Us | Phone: 1.234.567.8901
| | Email: some.guy#somedomain.com
Based on the information provided, yes - it's quite likely you'll need separate tables.
Tables are just groupings of similar information, and email doesn't relate to questions & answers. With more information about what you're looking to do, and any business rules around it, we can help you with structure if you'd like.
You could just have 1 table which has a page id column and a page content column. The page id being different for each page you want to store in the database. And the page content column can be a text field which contains the HTML you want to display on that page. Then on each page you would query the database passing the parameter for the page content you wanted to display.

Resources