I wish to select all records from a database and then combine matching keys and also adding their values.
Col1 col2
----- ------
ABC 2
ABA 3
ADD 1
AED 3
ABC 2
ABA 3
ADD 1
AED 3
So i would end up with
array("
ABC => 4,
ABA => 6,
ADD => 2,
AED => 6");
This is basic GROUP BY application:
SELECT Col1, SUM(col2) FROM tbl GROUP BY Col1
See http://sqlfiddle.com/#!2/8d1f8/1 for an example
Related
Database:
ID | CID | HOURS
1 | 201 | 8, 8, 8, 8
2 | 201 | 2, 4, 7, 5
3 | 201 | 4, 3, 7, 1
How can I extract the values in the HOURS column and add the values to produce the results of on a HTML table:
TOTAL HOURS: 14 | 15 | 22 | 14
I am assuming that the values in Hours column need to be inserted into an array? So, I did a while loop and exploded the results and got the following:
while($row = sqlsrv_fetch_object($result)) {
$hours = explode(', ', $hours)
}
I do a print_r($hours, 1) and get the following:
Array
(
[0] => 8
[1] => 8
[2] => 8
[3] => 8
Array
(
[0] => 2
[1] => 4
[2] => 7
[3] => 5
)
Array
(
[0] => 4
[1] => 3
[2] => 7
[3] => 1
)
How do I loop this to do the calculation?
Setting aside the comma-delimeted data being an anti-pattern, it's possible to return your aggregated values in a single query without needing to loop over anything by using string_split, the basics of which are:
select
Sum(case col when 1 then v end),
Sum(case col when 2 then v end),
Sum(case col when 3 then v end),
Sum(case col when 4 then v end)
from (
select v, row_number() over(partition by id order by id) col
from t
cross apply(
select Cast(value as int)v from String_Split(t.hours,',')
)v
)v
demo Fiddle
I have the following SQL table
ID | country_id | name
1 33 test1
2 77 test3
3 33 test5
4 1 test6
5 77 test7
6 33 test8
I want to order this by country_id where each country_id has it's own name (but not in another database).
EX:
$countries = array(
77 => 'Macedonia',
33 => 'Uruguay',
1 => 'Ghana'
);
So the result would be something like this:
ID | country_id | name
4 1 (G hana) test6
2 77 (M acedonia) test3
5 77 (M acedonia) test7
1 33 (U ruguay) test1
3 33 (U ruguay) test5
6 33 (U ruguay) test8
You'll be interested in MySQL's FIELD() function which will allow you to define a custom ORDER BY query:
SELECT
id, country_id, name
FROM
countries
ORDER BY
FIELD(country_id, 77, 33, 1);
FIELD() allows you to define an "ordered list" and then checks what index/position in the list the value you pass in is located at; you can use that to generate your custom ORDER BY.
If you have an array in PHP like you showed with $countries, you could easily generate the query with:
$country_ids = join(',', array_keys($countries));
$fieldClause = 'FIELD(country_id, ' . $country_ids . ');'
Alternatively, if you have a second reference table that contains country names, you could JOIN against that:
SELECT
a.id, a.country_id, a.name
FROM
your_table a
JOIN countries c
on a.country_id = c.id
ORDER BY
c.name;
I would recommend the latter approach since it's more portable.
You need to use the $countries array, sort it and use it in the ORDER BY:
sort($countries);
$order = implode(', ', array_keys($countries));
Now the array is sorted by the values and you can use the keys as the order in FIELD() as shown by newfurniturey:
SELECT id, country_id, name
FROM countries
ORDER BY FIELD(country_id, $order);
However, even with only 3 countries I would create another table and join that.
I have a table called Grades and inside I have some columns:
Id id_student Subjects grade
3 1 [->] Biology 8
4 1 [->] Math 4
5 1 [->] Sports 4
6 1 [->] Math 8
7 1 [->] English 9
8 4 [->] Sports 10
9 4 [->] English 7
I selected everything from this table where id_student = student logged in
$sth = $this->dbh->prepare("SELECT * FROM note WHERE id_elev = :id_elev");
$sth->bindParam(":id_elev", $_SESSION['id']);
$sth->execute();
$result = $sth->fetch(PDO::FETCH_ASSOC);
So all I selected is this:
Id id_student Subjects grade
3 1 [->] Biology 8
4 1 [->] Math 4
5 1 [->] Sports 4
6 1 [->] Math 8
7 1 [->] English 9
I want to make a average grade for Math , Biology , etc for this student but I want it without making a SELECT * FROM Grades WHERE $result['Subjects'] == 'Biology' because some students may not have this subject in their schedule.
I want something like this:
Id id_student Subjects grade
4 1 [->] Math 4
6 1 [->] Math 8
But without WHERE $results['Subjects'] == 'Math';
I'm sorry it is hard to explain when you don't know a lot of english. I hope that someone understands what I wrote and give me an advice. I can make another table called Subject if it is necessary.
Check out this fiddle:
http://sqlfiddle.com/#!2/8ee5a/3
I think it does what you need. If not, it's a great place to test the query.
I used the GROUP BY function AVG() to get the average grade for each subject.
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_avg
Here is the schema and query:
CREATE TABLE grades
(
Id int auto_increment primary key,
id_student int,
Subjects varchar(20),
grade int(1)
);
INSERT INTO grades
(Id, id_student, Subjects, grade)
VALUES
('3', '1', 'Biology', 8),
('4', '1', 'Math', 4),
('5', '1', 'Sports', 4),
('6', '1', 'Math', 8),
('7', '1', 'English', 9);
SELECT id_student, Subjects, AVG(grade) FROM grades GROUP BY Subjects;
The query below is an example of the use I mentioned in my comment
-- The AVG() function returns the average value of a numeric column.
-- because you are executing an aggregate function on the Grade column you have to specify which columns to group the results together by.
SELECT
Id
,Subject
,AVG(Grade) as 'Average Grade'
FROM
Result
GROUP BY
Id
,Subject
I have the folowing query that shows my products.
SELECT DISTINCT productsmap.id, attributes_product.waarde,
attributes_product.att_id, productsmap.name, productsmap.category
AS categoryId, brand.naam AS brand, productsmap.sku, categorie.name AS
category, productsmap.price, productsmap.shops
FROM productsmap
INNER JOIN categorie ON productsmap.category = categorie.id
INNER JOIN brand ON productsmap.brand = brand.id
INNER JOIN attributes_product ON productsmap.id = attributes_product.pmapid
WHERE productsmap.category
IN ( 2, 3, 4, 5, 6, 7, 8 )
AND productsmap.shops >0
AND (
productsmap.price >= 3.94
AND productsmap.price <= 204.99
)
AND productsmap.online =1
LIMIT 0 , 30
It gives the folowing results I cropped a bit:
(id) (waarde) (att_id) (name) (categoryId) (brand) (sku)
2 109 1 Name 4 Merk 70000
2 2013 2 Name etc etc etc
2 123 3 Name etc etc etc
3 103 1 Name2 etc etc
3 2012 2 Name2
3 123 3 Name2
4 110 1 3name
4 2013 2 3name
4 102 3 3name
Whit multiple times the same id and name only diffrent att_id and waarde. But i need to add to my query (attributes_product.att_id = 1 and waarde = 109) and (attributes_product.att_id = 2 and waarde = 2013)
But this is not possible because it are diffrent results. How can I solve this issue? Or on what can i search to solve this issue?
It attributes.product are att_id and waarde
This question already has answers here:
Sort array by two specifics values in PHP
(2 answers)
Closed 9 years ago.
I have data like this in mysql sort by id ASC:
NOTE: total is not in mysql, total is from price * total_item -> for example
id name total
---- ----------- ----------
1 item1 3
2 item2 5
3 item3 1
4 item4 2
5 item5 4
and I want to sort it in php
first, I sort the total to get the highest total in first place
//insert total into list
for($i=0;$i<5;$i++){
$total_list[] = $total;
$b = $total_list;
rsort($b);
//display total from highest to lowest
echo $b[$i];
}
the result will be like this:
id name total
---- ----------- ----------
1 item1 5
2 item2 4
3 item3 3
4 item4 2
5 item5 1
ok, I already got the total sorted according to my code above
so to get the name sorted too, I have to sort it but I already tried the same way as I sorted the total but the result is different
nah, I want the result is like this
id name total
---- ----------- ----------
1 item2 5
2 item5 4
3 item1 3
4 item4 2
5 item3 1
This can (and should) all be done from the SQL query; something like:
SELECT `id`, `name`, `price` * `total_item` AS `total`
FROM `mytable`
ORDER BY
`price` * `total_item` DESC,
`id` ASC
When ORDERing, you can't use the name given in AS, but you can order on the same calculation.
I tried something like this: using asort
$data = array(
"item1"=>"1",
"item2"=>"2",
"item3"=>"5",
"item4"=>"3",
"item5"=>"4"
);
asort($data);
print_r($data);
Resut: Array ( [item1] => 1 [item2] => 2 [item4] => 3 [item5] => 4 [item3] => 5 )
In order to obtain the highest total value and name, get the last element on the array. Though you can manipulate the names and keys by using foreach.
If we add foreach like this:
foreach($data as $key=>$val){
echo "Name:".$key." Total:".$val."<br>";
}
Result:
Name:item1 Total:1
Name:item2 Total:2
Name:item4 Total:3
Name:item5 Total:4
Name:item3 Total:5