Three small questions regarding datatypes and redundant indexes in MySQL

First Question
I have a table (several but for this example we’ll use one) where I want to track the created timestamp and the modified timestamp for the row. When I set this up, I tried making both fields a timestamp datatype, not null and a default of CURRENT_TIMESTAMP. However, MySQL has some limitation where you can’t have two columns in the same table with a default of CURRENT_TIMESTAMP. I didn’t really look into it, I just figured I’d work around the issue by removing the default value from the modified field. Nope, I get errors because the default value for a timestamp datatype can not be none when not null is set. So, I decided to work around this once more and remove the not null option. This isn’t ideal but it works. I’m wondering what other people do as this has to have been encountered by many of you before.

Second Question
[SIZE=4][SIZE=2]I have a many to many lookup table, for example:

Tests

id | name

Student
[/SIZE][/SIZE]----------
id | name

Lookup Table

tests_id | students_id | grade
-----------------------------

[SIZE=2]Here’s the problem, the grade can either be a count (eg: a number between 1-30) or it can be a percentage. Normally I’d store a count as an integer and a percentage as a decimal(3,2) but considering the grade can be either, I’m not sure what datatype to use or if this is even the proper way to go about this. Currently, I just have an integer datatype and adjust it programmatically which probably isn’t ideal.

Third Question[SIZE=4][SIZE=2]
I’ve been using SQLyog’s find redundant indexes feature and I’m confused slightly about what it’s finding. Here is an example:

[/SIZE][/SIZE][/SIZE]



As you can see, I have three indexes. One for the primary key and one for each foreign key. As I understand it, in multi-column indexes, the values are indexed together, not separate. Therefore, the need for the two foreign key indexes. If that’s the case, then niether foreign key should be redundant. However, as you can see it thinks I’m wrong (and maybe I am). So, if I am wrong, then technically shouldn’t both foreign keys be considered redundant to the primary key?

Thank you in advance.

  1. use DATETIME for both columns, and always provide a value, both created and modified

  2. use two grade columns, both nullable, instead of one

  3. suppose you have a phone book, which lists people by last name, and within last name by first name – do you need another phone book which lists people by last name only?

  1. As for keeping track of time zones, should I convert everything to UTC before entering the data with UTC_TIMESTAMP()?

  2. What happens down the road if there suddenly becomes 3 ways for grades to be entered, I’d have to alter my table. Is there another way to do this?

  3. How come both foreign keys aren’t considered redundant then, since both are in the primary key index?

Thank you.

Are you able to find all “'Ryan”'s by using the phone book?

that is correct, you would

yes, but in my opinion it’s even messier

I seem to be getting confused on how it knows which foreign key is the “first name” or “last name”.

Alright, no problem. Do you have an article or any material I can read up on the different way?

instead of one relationship table holding three different grade columns, three separate relationship tables, each one having only one grade column, which will always be the same type

Oh wow, that is messy. Nope, won’t be doing that.

sorry to have confused you

let’s use your example instead of firstname and lastname

here’s the sample data –

category_id   commodity_id

   36            20453
   42            20735
   26            20876
   55            20945
   15            20784
   25            20599
   33            20594
   26            20735

okay, now let’s look at your indexes

the first index, the composite index, looks like this –

category_id   commodity_id

   15            20784
   25            20599
   26            20735
   26            20876
   33            20594
   36            20453
   42            20735
   55            20945

naturally, an index also contains a pointer (not shown) which identifies where these rows are on the disk

the second index, the one on commodities, looks like this –

commodity_id
   20453
   20594
   20599
   20735
   20784
   20876
   20945

again, each index entry contains a pointer to where the row is on the disk

finally, the third index –

category_id

   15
   25
   26
   33
   36
   42
   55

thus, if you were going to write a query to return something for a specific category, you could use either the first index (the composite one) or the third one

the second index is ~not~ redundant, because neither the first one nor the third one can be used to find a specific commodity

Ah thank you rudy, I definitely understand now. I wasn’t aware that the order mattered.

I have another question regarding question #2.

So I have two grade columns, one or the other will always have a value but never both.

Therefore, is using SELECT CONCAT(column1, column2) as column3 a good way to get all values into one array?

CONCAT doesn’t produce an array, it produces a single character string

and if (as discussed earlier) one of those columns is null, then the result will be null

it’s best to analyze the results (i.e. which column is null and which contains a value) in your application code

Perfect, thanks again.

How about:

GRADE_TYPES

id | name

Lookup Table

tests_id | students_id | grade_type_id | grade

[QUOTE=itmitică;5156820]How about:

GRADE_TYPES

id | name

Lookup Table

tests_id | students_id | grade_type_id | grade
----------------------------------------------------[/QUOTE]

This wouldn’t alleviate the datatype problem though, would it? I’d have to store a percent in an int type.

Or all be just text…?
Future grades could be ‘A’, ‘Very Good’…

Hmm, that gives me some thinking to do. I’ll have to see where this project is headed in the future. It might make more sense to do it that way if there’s going to be additional ways to grade these tests in the future.

that’s right, it wouldn’t

:slight_smile:

OK then.

How about:

Lookup Table

tests_id | students_id | grade_type_id | grade_id

and for each type of grade (int, percentage, text) there be separate tables: GRADES_INT, GRADES_PERCENTAGE, GRADES_TEXT.

EDIT: Or maybe different partitions in the same GRADES table! This sounds better. Together with the extra null fields for each type of grade: int, percentage, char.

The grade_type_id would point to the right grades table, and the grade_id would point to a record in that particular grades table.

All in all, having int and percentage saved as text, and to have only one grades table would be better, I think. What I suggested first. Doing something like ‘85.25’*1 would implicitly cast the int/percentage value stored as text back to numeric.

GRADE_TYPES

1 | Z (http://en.wikipedia.org/wiki/Integer)
2 | % (http://en.wikipedia.org/wiki/Percentage)
3 | α (http://en.wikipedia.org/wiki/Alpha)

LOOKUP

203 | 158 | 1 | 8
508 | 158 | 2 | 86.56
1056 | 158 | 3 | B+