Understanding DB Design - php

I wanted to make a database to store examination marks. I was wondering if it is better to have
a table for each subject which will make a single record for a roll number
or
have a marks table which will have multiple records for a roll number for every subject
Since the number of subjects is not fixed, which approach would be better.
For the first method, As the tables would be created using php dynamically, so the table names will become a variable, so that will mean extra sanitisation work,
For the second method, the roll number will have many duplicates
Since I am new to DBMS, so any insight is appreciated.

Here's one good reason to choose the second method over the first. Let's say you want to get all marks for a specific roll number. (Using 1 for example.) With the second method, it's just:
SELECT * FROM marks WHERE roll_number = 1;
With the first method (unless someone else knows a better way to do it), it's:
SELECT * FROM subject_a WHERE roll_number = 1
UNION
SELECT * FROM subject_b WHERE roll_number = 1
UNION
SELECT * FROM subject_c WHERE roll_number = 1
...
and so on, for each one of your unknown number of subject tables.

Related

Understanding COUNT() as `count`

I'm currently learning how to build a site in PHP MySQL. However, I seem to fail to understand COUNT() as count and wouldn't mind some further explanation.
I get the principles of COUNT, 0 || 1, and how it returns all the values that pertain to that query.
But, don't see how COUNT as count works. Anyhow, this is how the code I'm writing goes - so we have a working example - and where I first became perplexed.
"SELECT COUNT(id) as count, id
FROM user
WHERE email='$email' AND password='".md5$password."'"
That is what is called alias which is sometimes used to show a more appealing column header to users or the calling code
SELECT COUNT(`id`) as `count`....
will print
count
--------
5
The alias standing as the column header instead of any arbitrary string: See the SQLFiddle to see the difference
From the fiddle you can see that the header column looks somehow e.g.
count(*)
--------
5
With Count() you can count the returning rows of a result set. The also the official MySQL documentation about count:
Databases are often used to answer the question, “How often does a certain type of data occur in a table?” For example, you might want to know how many pets you have, or how many pets each owner has, or you might want to perform various kinds of census operations on your animals.
Counting the total number of animals you have is the same question as “How many rows are in the pet table?” because there is one record per pet. COUNT(*) counts the number of rows, so the query to count your animals looks like this:
SELECT COUNT(*) FROM pet;
The part with AS count means that this colum will get a name which you can use e.g. in PHP. See also this explenation on w3schools:
You can give a table or a column another name by using an alias. This can be a good thing to do if you have very long or complex table names or column names.
An alias name could be anything, but usually it is short.
as count is just an alias. You can use as for any field or method selected. it means you change the name of the column being returned in your dataset.
SELECT `field` as another_name
So:
SELECT COUNT(*) as `count`
Just renames the column from COUNT(*) to count making it easier to work with whereever you are maniuplating your result set.
It also makes for easier access within your current query. Many would do the following with large table names:
SELECT * FROM `table_with_ridiculous_name` as twrn WHERE twrn.id = 1
If you ran this sql:
SELECT COUNT(id), id ....
You would get (after doing a *_fetch_assoc) $row['numberofrecordshere'] which would be very hard to echo (or use in a comparison) unless you knew how many records there would be (which would defeat the purpose of this result, anyway)
Returning it as count allows you to get to it in the resulting array by using $row['count']

unused number mysql

How can i get all of the records in a table that are out of
sequence so I know which account numbers I can reuse. I have a range
of account numbers from 50100 to 70100. I need to know which account
numbers are not stored in the table (not currently used) so I can use.
For instance say I have the following data in table:
Account Name
------ --------
50100 Test1
50105 Test2
50106 Test4
..
..
..
I should see the results:
50101
50102
50103
50104
because 50101-50104 are available account numbers since not currently in
table.
copied from http://bytes.com/topic/sql-server/answers/78426-get-all-unused-numbers-range
With respect to MYSQL and PHP.
EDITED
My range is 10000000-99999999.
My present way is using MySql query:
'SELECT FLOOR(10000000 + RAND() * 89999999) AS random_number FROM contacts WHERE "random_number" NOT IN (SELECT uid FROM contacts) LIMIT 1';
Thanks.
solution 1:
Generate a table with all possible accountnumbers in it. Then run a query similar to this:
SELECT id FROM allIDs WHERE id NOT IN (SELECT id FROM accounts)
Solution 2:
Get the whole id colummn into an array in php or java orso. Then run a for-loop to check if the number is in the array.
$ids = (array with all ids form the table)
for($i=50100;$i<=70100;$i++){
if(array_search($i, $ids) != -1){
$availableids[] = $i;
}
}
one way would be to create another table - fill it will all allowable numbers, then write a simple query to find the ones in the new table that are not in the original table.
Sort the accounts in the server, and find jumps in PHP while reading in the results. Any jump in the sorted sequence is "free for use", because they are ordered. You can sort with something like SELECT AccountNumber FROM Accounts SORT ASCENDING;.
To improve efficiency, store the free account numbers in another table, and use numbers from this second table until no more remain. This avoids making too many full reads (as in the first paragraph), which may be expensive. While you are at it, you may want to add a hook in the part of the code which deletes accounts, so they are immediately included in this second table, making the first step unnecessary.

How to properly get flag value from database using PHP?

Imagine it like this. There is a field in my database called flags in which are added or removed data like this:
UPDATE people SET flags=flags|16 WHERE ....
UPDATE people SET flags=flags|128 WHERE ....
UPDATE people SET flags=flags&~16 WHERE ....
UPDATE people SET flags=flags&~128 WHERE ....
For instance this field can have value like 65536 or more or less. My question is - How to get specific flag from this field using PHP code? I mean something like this:
SELECT * FROM people WHERE flags=16;
But the result will return all people with not just number 16 in field but it will return people with flag 65536, people with 16 but not people with 2 or 1. Which SELECT query should I use here in my php code or maybe some specific PHP integrated functions? Thank you.
Assuming flags is a bitfield and you want to select rows where bit #4 (10000) is set
SELECT * FROM people WHERE flags & 16;
This is not ideal though as you're losing out on all that referential goodness that DBs are good for.
What you should have is two new tables; flags and people_flags. The former contains all the flags (id and name columns should be sufficient). The latter contains flag_id and people_id columns, creating a many-to-many relationship (see junction table).
The logic is not correct though. You cant have just one flag that contains 16 as its not unique.
Lets say you have DB with this rows
name:Jhon tel:012345 email:test#test.com flags:16
name:Mike tel:012344 email:mike#test.com flags:16
name:Sarah tel:012346 email:sarah#test.com flags:2442
to select flags 16 from this table with using Select statement you will get two rows of data you can either use Distinct or get flags to be unique

MySQL specify every column in query rather than using SELECT * [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Which is faster/best? SELECT * or SELECT column1, colum2, column3, etc
I recall reading a number of years ago that in the scenario where you wanted to select everything from a MySQL table it was more efficient and better practice to specify every column rather than use the lazy and less-efficient SELECT * approach.
I am struggling to find any evidence of this online, so i'm not sure if it applies with newer versions of MySQL and PHP.
Would it be better to specify every column in my SELECT rather than using SELECT *?
SELECT * FROM golf_course WHERE id = 2;
Select * is inherently less efficient because the database has to look up the columns. Further if you have even one join you are sending unnecessary repeated data which is wasteful of database and network resourses, particularly if you do it on every query. Finally, select * doesn't specify the order of the columns, so if someone foolish drops and recreates the table with the columns in a different order, you may suddenly have your Social security number showing up in your first name column on the form or report. And if someone adds a column that you don't want displayed everywhere (say for auditing purposes or notes about the customer that you don't want the customer to ever see) you are in trouble. Further, if you do add columns, you need to determine where they should show up anyway and why not just have them willy nilly show up everywhere. Select * is an extremely bad SQL antipattern.
Yes.
Your query will be easier to understand
You will only select the columns you need
If you specify all columns, it will be easier to remove those you don't want later but if you didn't and you want to do later, you will need to type all the columns
You'll be able to arrange the columns the way you want and reference them in your code even if more columns are added to the table later
You can easily add computation, concatenation
and more
Performance-wise, I am not sure
IMHO, calling a SELECT * will have to read all fields where are calling only the required fields will be more efficient. And when you are querying a larger database the performance may be affected using SELECT *

Optimizing an MYSQL COUNT ORDER BY query

I have recently written a survey application that has done it's job and all the data is gathered. Now i have to analyze the data and i'm having some time issues.
I have to find out how many people selected what option and display it all.
I'm using this query, which does do it's job:
SELECT COUNT(*)
FROM survey
WHERE users = ? AND table = ? AND col = ? AND row = ? AND selected = ?
GROUP BY users,table,col,row,selected
As evident by the "?" i'm using MySQLi (in php) to fetch the data when needed, but i fear this is causing it to be so slow.
The table consists of all the elements above (+ an unique ID) and all of them are integers.
To explain some of the fields:
Each survey was divided into 3 or 4 tables (sized from 2x3 to 5x5) with a 1 to 10 happiness grade to select form. (questions are on the right and top of the table, then you answer where the questions intersect)
users - age groups
table, row, col - explained above
selected - dooooh explained above
Now with the surveys complete and around 1 million entries in the table the query is getting very slow. Sometimes it takes like 3 minutes, sometimes (i guess) the time limit expires and you get no data at all. I also don't have access to the full database, just my empty "testing" one since the costumer is kinda paranoid :S (and his server seems to be a bit slow)
Now (after the initial essay) my questions are: I left indexing out intentionally because with a lot of data being written during the survey, it would be a bad idea. But since no new data is coming in at this point, would it make sense to index all the fields of a table? How much sense does it make to index integers that never go above 10? (as you can guess i haven't got a clue about indexes). Do i need the primary unique ID in this table? I
I read somewhere that indexing may help groups but only if you group by the first columns in a table (and since my ID is first and from my point of view useless can i remove it and gain anything by it?)
Is there another way to write my query that would basically do the same thing but in a shorter period of time?
Thanks for all your suggestions in advance!
Add an index on entries that you "GROUP BY" or do "WHERE". So that's ONE index incorporating users,table,col,row and selected in your case.
Some quick rules:
combine fields to have the WHERE first, and the GROUP BY elements last.
If you have other queries that only use part of it (e.g. users,table,col and selected) then leave the missing value (row, in this example) last.
Don't use too many indexes/indeces, as each will slow the table to updates marginally - so on really large system you need to balance queries with indexes.
Edit: do you need the GROUP BY user,col,row as these are used in the WHERE. If the WHERE has already filtered them out, you only need group by "selected".

Categories