how can I count Mysql Field Rows?
For example I have table called student_attendance where we have 4 fields: absent, present, holiday, leave.
There is list of 10+ students, each student value will go to its own field, like if for one student we selected absent, 1 value will go to absent field and if someone select present, 1 value will go to present field.
Now what i want is
Each time attendance take, new row insert in student_attendance table for the student.
So if there are 10 Rows in student_attendance table, how can i + all of them
Like if there are 10 rows of present field, 3 rows are empty and 7 rows have 1 value, how can i count it so that the total value of specific field 1+1+1+1+1+1+1 can comes in php so it show 7 ?
SELECT SUM(present) AS presence_days
FROM student_attendance
This will result:
+---------------+
| presence_days |
+---------------+
| 7 |
| |
+---------------+
Example SQL (Demo):
select count(*) from table_name where present_field=1;
Try this:
SELECT SUM(absent), SUM(present), SUM(holiday), SUM(leave)
FROM student_attendance
GROUP BY sudentId;
Related
Take the following dataset:
id | Number
1 | 6534
1 | 765
1 | 1234
2 | 744
2 | 6109
3 | 333
3 | 9888
3 | 3112
3 | 98432
I want to show the highest Number for each id.
So Like this:
id | Number
1 | 6534
2 | 6109
3 | 98432
How can I do this with a SELECT statement?
I've already tried the following:
SELECT * FROM mytable ORDER BY id, Number Desc
But this shows the entire dataset.
I'm not trying to get the number of occurences. I am trying to get the highest Number grouped by id but can't get it to work.
SELECT id, MAX(Number) as Number FROM mytable GROUP BY id
You can try :
Select id,max(Number) from Your_Table group by id
Your Query that you have tried, it will only order your Data table by the given parameters.
In the meantime, What i have proposed to you, will select the two columns you want to diplay (the id, and the maximum of the column "Number").
And the group by will help to the maximum of each group. That's why a group by id is the right clause to have the maximum of each group of Ids.
Most of time the id field is incremental but for your case you can use.
SELECT MAX(number) FROM `user` GROUP BY id
Where number is the column name from which you want to find MAX, and user is your table name.
I'm trying to create a query from two tables, Table 1 contains a contract between the company and the customer.
Table 2 contains a statement payments.
What I want to do is: assembling late payments from Table 2 values, so that the value of each batch 250$ and displayed as follows:
____________________________________
Client | late payments | total
____________________________________
John | 2 | 500 (250*2)
____________________________________
Table2 like this:enter image description here
First use Concat for create date and cast string as date and compare with paydate at last use group by and calculate sum or count of late paid
SELECT contract_id,count(contract_id) late_payments,sum(paid) total FROM `table`
where cast(Concat(year.'-',month,'-',day) as date) < paydate
Group by contract_id
My table looks like this:
+------------------------+
| id | title | position |
+------------------------+
| 1 | test 2 | 3 |
+------------------------+
| 2 | test 3 | 1 |
+------------------------+
| 3 | test 1 | 0 |
+------------------------+
I found this query which retrieves the rows ordered based on the position field which holds the id of the predecessor.
SELECT
*
FROM
mytable AS t1
LEFT JOIN
mytable AS t2
ON t2.position = t1.id
I wonder why this is working because there is no order by clause and the database should't know that position 0 is the row to start at.
The result is dependent on the order you inserted the rows into the table. If, for example, you had inserted the row with id=3 before you inserted the row with id=2, then you would have got a non-sorted result.
As it stands, you are pulling the data out of t1 in the order of id because that is the order you put the elements into the table
See http://sqlfiddle.com/#!2/63a925/2 and try it for yourself.
N.B. Databases are not guaranteed to work as you state, it is simply that most databases work this way. You should not rely on this behaviour as a minor change to the schema or query could ruin your whole day! Note also that if id is a (primary?) key, the insert order will probably be overridden by the fact that the database will pull the rows out in the order of the index.
That query is joining in table 2 based on the ID in table 1 equaling the position in table 2. Since the IDs in table 1 are sequential, the output appears to be sorted
I've got two tables which are related to each other. I want to change table 1 status to updated when I insert new values into table 2 and return mysqli_affected_rows() for table 1
table 1: products
id | name
1 | product
table 1: categories
id | name | product_id
1 | cat 1 | 1
2 | cat 2 | 1
is this possible?!
You show the structure of the tables, but don't include any column that should be updated. This makes me think that you don't really want an update. You just want a query that returns whether a given product is in the categories table.
If so, the following may do what you want:
select p.*,
coalesce( (select 1 from categories c where c.productid = p.id limit 1), 0) as InCategories
from products p;
If you try to go another route where you actually store the value in the table, you will need to use a stored procedure or triggers. Do consider, though, what happens when you delete or update a row. insert is not the only way to modify data in a table.
I have a table witch has 45 columns but only a few of these are yet completed. This table is continuously updated and added etc. In my auto-complete function i want to select these records ordered by the most completed fields(i hope you understand)?
One of the solutions is to create another filed (the "rank" field) and create a php function that selects * the records and gives a rank for each record.
... but i was wondering if there is a more simple way of doing this only whit a single ORDER BY?
MySQL has no function to count the number of non-NULL fields on a row, as far as I know.
So the only way I can think of is to use an explicit condition:
SELECT * FROM mytable
ORDER BY (IF( column1 IS NULL, 0, 1)
+IF( column2 IS NULL, 0, 1)
...
+IF( column45 IS NULL, 0, 1)) DESC;
...it is ugly as sin, but should do the trick.
You could also devise a TRIGGER to increment an extra column "fields_filled". The trigger costs you on UPDATE, the 45 IFs hurt you on SELECT; you'll have to model what is more convenient.
Note that indexing all fields to speed up SELECT will cost you when updating (and 45 different indexes probably cost as much as a table scan on select, not to say that the indexed field is a VARCHAR). Run some tests, but I believe that the 45-IF solution is likely to be the best overall.
UPDATE:
If you can rework your table structure to normalize it somewhat, you could put the fields in a my_values table. Then you would have a "header table" (maybe with only a unique ID) and a "data table". Empty fields would not exist at all, and then you could sort by how many filled fields are there by using a RIGHT JOIN, counting the filled fields with COUNT(). This would also greatly speed up UPDATE operations, and would allow you to efficiently employ indexes.
EXAMPLE (from table setup to two normalized tables setup):
Let us say we have a set of Customer records. We will have a short subset of "mandatory" data such as ID, username, password, email, etc.; then we will have a maybe much larger subset of "optional" data such as nickname, avatar, date of birth, and so on. As a first step let us assume that all these data are varchar (this, at first sight, looks like a limitation when compared to the single table solution where each column may have its own datatype).
So we have a table like,
ID username ....
1 jdoe etc.
2 jqaverage etc.
3 jkilroy etc.
Then we have the optional-data table. Here John Doe has filled all fields, Joe Q. Average only two, and Kilroy none (even if he was here).
userid var val
1 name John
1 born Stratford-upon-Avon
1 when 11-07-1974
2 name Joe Quentin
2 when 09-04-1962
In order to reproduce the "single table" output in MySQL we have to create a quite complex VIEW with lots of LEFT JOINs. This view will nonetheless be very fast if we have an index based on (userid, var) (even better if we use a numeric constant or a SET instead of a varchar for the datatype of var:
CREATE OR REPLACE VIEW usertable AS SELECT users.*,
names.val AS name // (1)
FROM users
LEFT JOIN userdata AS names ON ( users.id = names.id AND names.var = 'name') // (2)
;
Each field in our logical model, e.g., "name", will be contained in a tuple ( id, 'name', value ) in the optional data table.
And it will yield a line of the form <FIELDNAME>s.val AS <FIELDNAME> in the section (1) of the above query, referring to a line of the form LEFT JOIN userdata AS <FIELDNAME>s ON ( users.id = <FIELDNAME>s.id AND <FIELDNAME>s.var = '<FIELDNAME>') in section (2). So we can construct the query dynamically by concatenating the first textline of the above query with a dynamic Section 1, the text 'FROM users ' and a dynamically-built Section 2.
Once we do this, SELECTs on the view are exactly identical to before -- but now they fetch data from two normalized tables via JOINs.
EXPLAIN SELECT * FROM usertable;
will tell us that adding columns to this setup does not slow down appreciably operations, i.e., this solution scales reasonably well.
INSERTs will have to be modified (we only insert mandatory data, and only in the first table) and UPDATEs as well: we either UPDATE the mandatory data table, or a single row of the optional data table. But if the target row isn't there, then it must be INSERTed.
So we have to replace
UPDATE usertable SET name = 'John Doe', born = 'New York' WHERE id = 1;
with an 'upsert', in this case
INSERT INTO userdata VALUES
( 1, 'name', 'John Doe' ),
( 1, 'born', 'New York' )
ON DUPLICATE KEY UPDATE val = VALUES(val);
(We need a UNIQUE INDEX on userdata(id, var) for ON DUPLICATE KEY to work).
Depending on row size and disk issues, this change might yield an appreciable performance gain.
Note that if this modification is not performed, the existing queries will not yield errors - they will silently fail.
Here for example we modify the names of two users; one does have a name on record, the other has NULL. The first is modified, the second is not.
mysql> SELECT * FROM usertable;
+------+-----------+-------------+------+------+
| id | username | name | born | age |
+------+-----------+-------------+------+------+
| 1 | jdoe | John Doe | NULL | NULL |
| 2 | jqaverage | NULL | NULL | NULL |
| 3 | jtkilroy | NULL | NULL | NULL |
+------+-----------+-------------+------+------+
3 rows in set (0.00 sec)
mysql> UPDATE usertable SET name = 'John Doe II' WHERE username = 'jdoe';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> UPDATE usertable SET name = 'James T. Kilroy' WHERE username = 'jtkilroy';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0 Changed: 0 Warnings: 0
mysql> select * from usertable;
+------+-----------+-------------+------+------+
| id | username | name | born | age |
+------+-----------+-------------+------+------+
| 1 | jdoe | John Doe II | NULL | NULL |
| 2 | jqaverage | NULL | NULL | NULL |
| 3 | jtkilroy | NULL | NULL | NULL |
+------+-----------+-------------+------+------+
3 rows in set (0.00 sec)
To know the rank of each row, for those users that do have a rank, we simply retrieve the count of userdata rows per id:
SELECT id, COUNT(*) AS rank FROM userdata GROUP BY id
Now to extract rows in "filled status" order, we do:
SELECT usertable.* FROM usertable
LEFT JOIN ( SELECT id, COUNT(*) AS rank FROM userdata GROUP BY id ) AS ranking
ON (usertable.id = ranking.id)
ORDER BY rank DESC, id;
The LEFT JOIN ensures that rankless individuals get retrieved too, and the additional ordering by id ensures that people with identical rank always come out in the same order.