Each user must fill each month a number of parameters.
The number of parameters that need to supplement it varies from user to user, and
each user can add a new parameter (but they can not delete existing
ones if they already have values filled in).
EX: user_1 has: param_1, param_2; user_2 has: param_1, param_3, param_4, and so.
I have to sum these parameters at the user level.
I have two problems:
which is the best option for table structure?
considering: the max number of parameters a user cah have is 12; the number of active users will reach around 5000 (i hope)
distinct columns
| user_id | month | param_1 | param_2 | ... | param_12|
distinct rows:
| user_id | month | param_id | param_value |
| 001 | nov-2012 | param_1 | 100 |
| 001 | nov-2012 | param_2 | 125 |
| 002 | nov-2012 | param_1 | 110 |
| 002 | nov-2012 | param_3 | 150 |
| 002 | nov-2012 | param_4 | 175 |
and how can I calculate the sum of parameters fosr each user, considering the best option for table structure?
I think the second approach is the best suited for your case because in that case you are not wasting any memory and in future if you have to extend your database then also it not need any significant changes to the database.
Now the second problem of summing the parameter then you can fetch all the record of a particular user by its user_id and then add all those values
You can write query as follow's
$query = "SELECT SUM(param_value) FROM table_name WHERE param_id = $id";
mysql_query($query);
Related
I have 2 tables. One with a list of clients and another with a list of data. I am trying to create a table in my view that lists the client name along with the sum of a column(job_total) in the data table. I am able to write a query that works fine in most situations. The problem is, if I have not yet created a record in the data table I need to still display the client name with a balance of zero on my table in my view. Need some direction on how to handle this. I was thinking I need to query my list of clients and loop through that query just not sure how to do it.
I want my view to look like below:
+-------------+---------+
| Client Name | Balance |
+-------------+---------+
| xxx | $75.00 |
| xxx | $100.00 |
| xxx | $0.00 |
+-------------+---------+
Here is a rough layout of the two tables in my database:
cj_clients
+----+-------------+
| id | client name |
+----+-------------+
| 1 | client1 |
| 2 | client2 |
| x | xxx |
+----+-------------+
cj_data
+----+-----------+-----------+
| id | client_id | job_total |
+----+-----------+-----------+
| 1 | 1 | 5.00 |
| 2 | 1 | 10.00 |
| 3 | 1 | 15.00 |
+----+-----------+-----------+
The below code returns the desired results except when no entries have yet been made to the cj_data table. Not sure how to still get the client in the table view with a balance of $0.
$this->db->select('client_name,client_id, sum(job_total) AS balance')
->from('cj_data')
->join('cj_clients','cj_data.client_id = cj_clients.id')
->group_by('client_name');
return $this->db->get()->result();
You need to give left join
$this->db->select('client_name,client_id, IFNULL(sum(job_total),0) AS balance')
->from('cj_data')
->join('cj_clients','cj_data.client_id = cj_clients.id',"left") // here
->group_by('client_name');
return $this->db->get()->result();
I wrote IFNULL condition if record not found or it will show all data for all clients in cj_clients
Note: the Default behaviour of CodeIgniter is it will add inner join
if join not specified
Hello I am facing hard time trying to realized this task. The problem is that I am not sure in which way this have to be proceeded and couldn't find tutorials or information about realizing this type of task.
The question is I have 2 tables and one connecting table between the two of them. With regular query usually what is displayed is the table header which is known value and them then data. In My case I have to display the table horizontally and vertically since the header value is unknown value.
Here is example of the DB
Clients:
+--------+------ +
| ID | client|
+--------+------ +
| 1 | Sony |
| 2 | Dell |
+--------+------ +
Users:
+--------+---------+------------+
| ID | name | department |
+--------+--------+-------------+
| 1 | John | 1|
| 2 | Dave | 2|
| 3 | Michael| 1|
| 4 | Rich | 3|
+--------+--------+-------------+
Time:
+--------+------+---------------------+------------+
| ID | user | clientid | time | date |
+--------+------+---------------------+------------+
| 1 | 1 | 1 | 01:00:00 | 2017-01-02 |
| 2 | 2 | 2 | 02:00:00 | 2017-01-02 |
| 3 | 1 | 2 | 04:00:00 | 2017-02-02 | -> Result Not Selected since date is different
| 4 | 4 | 1 | 02:00:00 | 2017-01-02 |
| 5 | 1 | 1 | 02:00:00 | 2017-01-02 |
+--------+------+---------------------+------------+
Result Table
+------------+--------+-----------+---------+----------+
| Client | John | Michael | Rich | Dave |
+------------+--------+-----------+---------+----------+
| Sony |3:00:00 | 0 | 2:00:00 | 0 |
+------------+--------+-----------+---------+----------+
| Dell | 0 | 0 | 0 | 2:00:00 |
+------------+--------+-----------+---------+----------+
First table Clients Contains information about clients.
Second table Users Contains information about users
Third Table Time contains rows of time for each users dedicated to different clients from the clients table.
So my goal is to make a SQL Query which will show the Result table. In other words it will select sum of hours which every user have completed for certain client. The number of clients and users is unknown. So first thing that have to be done is Select all users, no matter if they have hours completed or not. After that have to select each client and the sum of hours for each client which was realized for individual user.
The problem is I don't know how to approach this situation. Do I have first to make one query slecting all users then foreach them in the table header and then realize second query selecting the hours and foreaching the body conent, or this can be made with single query which will render the whole table.
The filters for select command are:
WHERE MONTH(`date`) = '$month'
AND YEAR(`date`) ='$year'
AND u.department = '$department'
Selecting single row for tume SUM is:
(SELECT SUM( TIME_TO_SEC( `time` ) ) FROM Time tm
WHERE tm.clientid = c.id AND MONTH(`date`) = '$month' AND YEAR(`date`) ='$year'
This is the query to select the times for a user , here by my logic this might be transformed with GROUP BY c.id (client id), and the problem is that it have to contains another WHERE clause which will specify the USER which is unknown. If the users was known value was for example 5, there is no problem to make 5 subsequent for each user WHERE u.id = 1, 2, 3 etc.
So here are the 2 major problems how to display in same query The users header and them select the sum of hours for each client corresponding the user.
Check out the result table hope to make the things clear.
Any suggestion or answer which can come to resolve this situation will be very helpful.
Thank you!
I am developing a project in zf2 using doctrine and I need to create a method to renumber the order field so that the values are sequential. Before:
+-----+-------+--------+------------+
| id | order | item | collection |
+-----+-------+--------+------------+
| 987 | 1 | apple | fruits |
| 46 | 2 | banana | fruits |
| 394 | 7 | grape | fruits |
| 265 | 30 | pear | fruits |
| 89 | 1 | squash | vegetables |
+-----+-------+--------+------------+
After:
+-----+-------+--------+------------+
| id | order | item | collection |
+-----+-------+--------+------------+
| 987 | 1 | apple | fruits |
| 46 | 2 | banana | fruits |
| 394 | 3 | grape | fruits |
| 265 | 4 | pear | fruits |
| 89 | 1 | squash | vegetables |
+-----+-------+--------+------------+
The order sequences are by collection, but I don’t need the method to renumber the entire dataset; just the records in a particular collection.
Some of the solutions I am considering include:
Temporary Table:
Dump the pertinent records in order into a new table,
Add a field called new_order that is an autonumber field,
Join the tables on the id field and update current_table.order =
new_table.new_order,
Delete the temporary table.
Cycle Through the Records and Update one at a Time:
$collection = … // results from select query where collection=fruits
n = 1;
For each ($collection as $item) {
// update query to set order=n where id=$item[id]
n += 1
}
Any other thoughts?
Very much, definitely, please, use the 2nd method... I.E. cycle through records and update.
Quick reason for not using temp tables:
If you're using a MySQL temporary table, it is visible to the current session; which could actually be shared by multiple sessions if you are using persistent connections. If you run the script twice at the same time, it could cause some data corruption. The same thing applies to creating real tables.
What you should do is:
Retrieve all your data, or at least retrieve them in logical batches (in this case, it could be done by retrieving only rows of a particular "collection", e.g. fruits)
Order the rows (this could also have been done previously within the SQL query)
Update the rows using a counter, exactly like you have proposed
I have a PHP script where you can (as admin) select how many input-fields there will be in a question form. Some of the fields are non optional, but som are (as many as you like).
The table in MySQL for collecting the answers looks like this:
id | userid | fname | ename | seat | optional
If the admin want it to be two optional input-fields then the result of one filled form would take three tows in the table:
| 5 | 3 | Peter | Pan | 4 | |
| | 3 | | | | opt.value1 |
| | 3 | | | | opt.value2 |
Is this really the best way to store this in? How would you solve it?
And also, how can I make shure that the userid is unique for the user? I can't use the auto-increment key value thing in MySQL because the same value is on three rows...
The way i learned it you have to use multiple tables. Like this:
Table1:
id | userid | fname | ename | seat
Table2:
userid | optional
Table2.userid is a reference to Table1.userid
Then the fields that has to be filed can be put into the first table and all the optional in the second.
If i follow your example your database should look like this:
Table1:
id | userid | fname | ename | seat
5 | 3 | Peter | Pan | 4
Table2:
userid | optional
3 | opt.value1
3 | opt.value2
By the way, why do you have both id and userid in Table1?
Best practice would be to store "id" and "optional" values in a separate table.
Then pull the information you want from it for each "id".
I am trying to get a list of distinct values from the columns out of a table.
Each column can contain multiple comma delimited values. I just want to eliminate duplicate values and come up with a list of unique values.
I know how to do this with PHP by grabbing the entire table and then looping the rows and placing the unique values into a unique array.
But can the same thing be done with a MySQL query?
My table looks something like this:
| ID | VALUES |
---------------------------------------------------
| 1 | Acadian,Dart,Monarch |
| 2 | Cadillac,Dart,Lincoln,Uplander |
| 3 | Acadian,Freestar,Saturn |
| 4 | Cadillac,Uplander |
| 5 | Dart |
| 6 | Dart,Cadillac,Freestar,Lincoln,Uplander |
So my list of unique VALUES would then contain:
Acadian
Cadillac
Dart
Freestar
Lincoln
Monarch
Saturn
Uplander
Can this be done with a MySQL call alone, or is there a need for some PHP sorting as well?
Thanks
Why would you store your data like this in a database? You deliberately nullify all the extensive querying features you would want to use a database for in the first place. Instead, have a table like this:
| valueID | groupID | name |
----------------------------------
| 1 | 1 | Acadian |
| 2 | 1 | Dart |
| 3 | 1 | Monarch |
| 4 | 2 | Cadillac |
| 2 | 2 | Dart |
Notice the different valueID for Dart compared to Matthew's suggestion. That's to have same values have the same valueID (you may want to refer to these later on, and you don't want to make the same mistake of not thinking ahead again, do you?). Then make the primary key contain both the valueID and the groupID.
Then, to answer your actual question, you can retrieve all distinct values through this query:
SELECT name FROM mytable GROUP BY valueID
(GROUP BY should perform better here than a DISTINCT since it shouldn't have to do a table scan)
I would suggest selecting (and splitting) into a temp table and then making a call against that.
First, there is apparently no split function in MySQL http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/ (this is three years old so someone can comment if this has changed?)
Push all of it into a temp table and select from there.
Better would be if it is possible to break these out into a table with this structure:
| ID | VALUES |AttachedRecordID |
---------------------------------------------------------------------
| 1 | Acadian | 1 |
| 2 | Dart | 1 |
| 3 | Monarch | 1 |
| 4 | Cadillac | 2 |
| 5 | Dart | 2 |
etc.