I have to create an SQLite DB that models a survey with some ordered content; this content can be a question, an image or a simple text field (just like Google Forms). Each content doesn't have anything to do with the other, except questions which can have a list of attached images to them.
What would be the best way to model this situation? I thought about creating a "Survey" table and a "Content" table that has only an integer ID, and that same ID is then "duplicated" into each table ("Question", "Image" or "TextField"), but then I think I would have to insert both values for the Content and values for a specific content (Question, Image or TextField) every time I need to insert a new content. I don't think it would be a big problem, but if there is an way to model this better, I would like some advice.
Your approach is an example of 'table per type' as defined in this answer.
Conceptually, you're saying "there are 3 kinds of content, and the one thing they share is their relationship with a survey, as captured in the content table". You might include in that table an explicit type indicator along the ID - this will make your code a little more explicit. You may also find you need to capture meta data like "status", "date_entered" etc. which is common across subtypes.
By including a type indicator column, you make it easy to find out what the type of a content item is. So, if you want to show the summary of a question, you could do something like
select content_type, count(*)
from content
where question_id = ?
group by content_type
to show the number and type of responses.
Related
I am sorry for the lngthy question, but it has to be precisely described, if it is to be answered.
I am building a schema-and-data application in SQL Server and .NET winforms.
Table ItemType holds the type of items, table ItemTypeColumn holds the columns for each type and finally, table ItemData holds all the data of the application.
An example of these would be:
<ul>
<li>ItemType: Customer, Customer Category, etc</li>
<li>ItemColumn: Customer Name, Description etc</li>
<li>ItemData: John Doe, International, etc</li>
</ul>
This leads to a very interesting chain of data retrieval. For instance:
<ul>
<li>Customer X is item ID 100</li>
<li>Category Y is item ID 60</li>
<li>To indicate that Customer X is of category Y - (to point towards it) we need to find the line that combines ItemID=100, ItemColumnID=[whatever the id of the item ItemColumn is] and then update the field Data with the ID of Category X (60).</li>
</ul>
I retrieve the data with a Select statement as follows:
SELECT * FROM (
SELECT ItemData.ItemID,
IC.ItemTypeID,
MAX(CASE WHEN ItemData.ItemColumnID = 28
THEN ItemData.Data ELSE NULL END) AS "Name",
MAX(CASE WHEN ItemData.ItemColumnID = 32
THEN ItemData ELSE NULL END)
AS "Code"
FROM ItemData as Data
INNER JOIN (
select *
from ItemColumns
where ItemTypeID=7) as IC
on ItemData.ItemColumnID=IC.ID
GROUP BY ItemData.ItemID, IC.ItemTypeID) as table1
INNER JOIN Item ON Item.ID=table1.ItemID
This works like a charm.
Now, I want to give my user the ability to create calculated columns with ability to select:
<ul>
<li>A column from this type item</li>
<li>A column from a parent type item</li>
<li>A value from a child type item </li>
<li>The specific data found in a specific row id</li>
</ul>
Here 's an example:
<ul>
<li>Item Type "Country" has 1 field: Name</li>
<li>Item Type "City" has 3 fields: Name, Population, Country (pointing to parent country)</li>
</ul>
I ' d like to give the user ability to create new columns that will hold calculated data (as opposed to data entry, like "name" or "decription").
I have managed to create an expression builder and a parser that actually works. Taking the above example into account, you can create a column Urban Population in type Country that brings the sum of column Population of all "children" Cities for each country. This, I accomplished with User Defined Functions, and virtual columns which I call in the select statement.
Here's the problem (finally): if I want to create a calculated column that references another calculated column, say Rural Population - that would show the Country Population (numeric field) minus the sum of Urban Cities (sum of population field for "child cities") it will not work because the newly "created" (in the selecte table) column cannot be referenced by peers.
I sense that I am on the wrong track, in general, concerning the calculated fields. Are there any best practices to follow? Is my approach wrong? Is there a workaround for the calculation-in-calculation error?
Thank you in advance - again, I am sorry for the length of this question.
The approach you are taking in database design is "Name/Key value pair" . Infact you are going one step further also storing the aggregate data in the same name value pair structure. This approach looks very flexible and is very tempting , however the RDBMS by architecture not design for this approach.
This works very well with small data does not with big data. Hence design of this kid mostly fails in production within few months of release.
Please refer following link :
http://geekswithblogs.net/darrengosbell/archive/2006/03/12/KVPsInDatabaseDesign.aspx
it is always suggested to design RDBMS with explicit column name and definition.
I have usually notice number and type of aggregation needs are not very complex and very different and mostly they can be determined in advance . Hence discouraging this approach of yours.
In some scenarios in which the flexibility is absolute needed , one can use external tools like : tableau, R or Python Panda/iPython etc. I understand for these tool to use the users needs to learn them.
It is really commendable Nassosk , that you could achieve all what you have told in your original post, i will interested in seeing your code :-).
Looks like you are designing a database over database :-)
Thank you
From what I 've read here and elsewhere my question is like asking "how should I go about if I want to jump off a skyscraper" - most people will tell you not to jump, instead of giving you their 5 cents :)
In any case, and since I 've put a lot of work to it up to now, I thought I might fail with dignity and go all the way, so here's the answer:
Since my select statement actually returns a virtual table (it transposes the data) it seemed totally plausible to add all the related tables in a dataset, create the relations among them on the fly in the dataset (yes, #user3851404 I am building a database over a database, it's quite rewarding though) and set the Expression property equal to my formula in the datacolumns that I want to display derrived data.
It actually works as expected. I will not comment on performance because I haven't stress-tested it yet, but whatever the outcome regarding performance, it seems that this is the only workaround.
it might be possible I'm searching for the wrong keywords, but so far I couldn't find anything useful.
My problem is quite simple: At the moment I get a list of individual Ids through a report parameter, I pass them to a procedure and show the results.
The new request is like this: Instead of showing the list for all individuals at once, there should be a list for each individual id.
Since I'm quite a beginner in srss, I thought the easiest approach would be the best: Create a subreport, copy the shown list, and create a subreport per individual id.
The amount of this IDs is dynamic, so I have to create a dynamic amount of subreports.
Funny enought, this doesnt seem to be possible. This http://forums.asp.net/t/1397645.aspx url doesnt show exactly the problem, but it shows the limit of the subreports.
I even ran trough the whole msdn pages starting http://technet.microsoft.com/en-us/library/dd220581.aspx but I couldnt find anything there.
So is there a possibility, to create a loop like:
For each Individual ID in Individual IDs, create a subreport and pass ONE ID to this?
Or is there another approach I should use to make this work?
I tried to create a 'Fake'-Dataset with no sql query but just for iterating the id list, but it seems the dataset needs a data-source...
As usual, thanks so far for all answers!
Matthias Müller
Or is there another approach I should use to make this work?
You didn't provide much detail about what sort of information needs to be included in the subreport, but assuming it's a small amount of data (say, showing a personnel record), and not a huge amount (such as a persons sales for the last year), a List might be the way to go.
I tried to create a 'Fake'-Dataset with no sql query but just for iterating the id list, but it seems the dataset needs a data-source...
All datasets require a data source, though if you're merely hard-coding some fake return data, any data source will do, even a local SQL instance with nothing in it.
I am looking for a solution or to be told it simply is not possible/good practice.
I currently have a database whereby I can create new orders and select from a lookup table of products that I offer. This works great for the most part but i would also like to be able to add random miscellaneous items to the order. For instance one invoice may read "End of Tenancy Clean" and the listed product but then have also an entry for "2x Lightbulb" or something to that effect.
I have tried creating another lookup table for these items but the problem is i don't want to have to pre-define every conceivable item before I can make orders. I would much prefer to be able to simply type in the Item and price when it is needed.
Is there any database design or workaround that can achieve this? Any help is greatly appreciated. FYI I am using Lightswitch 2012 if that helps.
One option I've seen in the past is a record in your normal items table labeled something like "Additional Service", and the application code will recognize this item and also require you to enter or edit a description to print with the invoice.
In the ERP system which we have at work, there is a flag in the parts table which allows one to change the description of the part in orders; in other words, one lists the part number in the order and then changes the description. This one off description is stored in a special table (called NONSTANDARD) which basically has two fields - an id field and the description. There is a field in the 'orderlines' table which stores the id of the record in the special table. Normally the value of this field will be 0, which means that the normal description of the part be displayed, but if it's greater than 0, then the description is taken from the appropriate row in the nonstandard table.
You mean something like this?
(only key attributes included, for brevity)
I'm trying to implement a feature similar to StackOverflow's tag feature. That a user can create a new tag, or by typing pull up a list of similar tags already created.
This is such a wonderful feature on this site and I find it sad that most sites do not have something like this. It's both robust, and yet very very flexible and best of all: driven by the community.
So I have these two tables:
Company
id
email
name
companySize
countryOfOrigin
industryid
Industry
id
description
Every time a user writes a new tag, I want to create one with a unique ID, and also be able to search for existing tags.
Will this database design allow for an easy and efficient implementation of this feature?
If not, please give a little guidance. :)
Whilst there's not a tremendous amount of information to go on, what you've listed should be fine. (The 'tag' being the 'description' field in the industry table, etc.)
As you might imagine, all of the real work is done outside of SQL, where you'll need to...
(Potentially) add new tag(s) that don't yet exist.
Associate the industry with the supplied tag(s).
(Potentially) prune previously used tags that may no longer be in use.
...every time you edit an industry.
That said, the key limitation of your proposed setup is that each company can only belong to a single industry. (i.e.: It can only have a single industry tag associated with it.)
As such, you might want to consider a schema along the lines of...
Company
id
...
countryOfOrigin
Industries
id
description
CompanyIndustriesLookup
companyID
industryID
...which would let you associate multiple industries/tags with a given company.
Update...
For example, under this setup, to get all of the tags associated with company ID 1, you'd use...
SELECT Industries.description FROM (CompanyIndustriesLookup, Industries)
WHERE companyID=1 AND industryID=Industries.ID
ORDER BY Industries.description ASC;
On a similar basis, to get all companies tagged with an industry of "testing", you'd use...
SELECT Company.name FROM (Company, Industries, CompanyIndustriesLookup)
WHERE Company.id=CompanyIndustriesLookup.companyID
AND Industries.id=CompanyIndustriesLookup.industryID
AND Industries.description="testing"
ORDER BY Company.name ASC
A very easy (if somewhat suboptimal, but it often does not matter) solution to use tags is to not have tag ids at all. So, you have:
Items
ItemId
Name
Description
...
ItemTag
ItemId
Tag
Adding a tag to an item is just adding the tuple to the ItemTag table, whether the tag already exists or not. And you don't have to do any bookkeeping on removing tags either. Just keep an index on ItemTag.Tag, to be able to quickly display all unique tags.
I'm developing a website with a custom search function and I want to collect statistics on what the users search for.
It is not a full text search of the website content, but rather a search for companies with search modes like:
by company name
by area code
by provided services
...
How to design the database for storing statistics about the searches?
What information is most relevant and how should I query for them?
Well, it's dependent on how the different search modes work, but generally I would say that a table with 3 columns would work:
SearchType SearchValue Count
Whenever someone does a search, say they search for "Company Name: Initech", first query to see if there are any rows in the table with SearchType = "Company Name" (or whatever enum/id value you've given this search type) and SearchValue = "Initech". If there is already a row for this, UPDATE the row by incrementing the Count column. If there is not already a row for this search, insert a new one with a Count of 1.
By doing this, you'll have a fair amount of flexibility for querying it later. You can figure out what the most popular searches for each type are:
... ORDER BY Count DESC WHERE SearchType = 'Some Search Type'
You can figure out the most popular search types:
... GROUP BY SearchType ORDER BY SUM(Count) DESC
Etc.
This is a pretty general question but here's what I would do:
Option 1
If you want to strictly separate all three search types, then create a table for each. For company name, you could simply store the CompanyID (assuming your website is maintaining a list of companies) and a search count. For area code, store the area code and a search count. If the area code doesn't exist, insert it. Provided services is most dependent on your setup. The most general way would be to store key words and a search count, again inserting if not already there.
Optionally, you could store search date information as well. As an example, you'd have a table with Provided Services Keyword and a unique ID. You'd have another table with an FK to that ID and a SearchDate. That way you could make sense of the data over time while minimizing storage.
Option 2
Treat all searches the same. One table with a Keyword column and a count column, incorporating SearchDate if needed.
You may want to check this:
http://www.microsoft.com/sqlserver/2005/en/us/express-starter-schemas.aspx