php mysql sum issue - php

I want to generate a report to accumulate the total stock quantity that has been ordered by different branches in a month, and each branch will sum up the quantity by merged (GROUP BY) stock.
i trimmed up my database table for easy understanding as below:
Item Branch Order_Quantity
---------------------------------------
Pencil Branch-A 5
Ruler Branch-D 3
Staple Branch-C 12
Pencil Branch-A 5
Ruler Branch-B 3
Staple Branch-C 2
Pencil Branch-A 10
Ruler Branch-A 6
Staple Branch-D 1
for example, below is draft of expected outcome result:
Item Branch-A Branch-B Branch-C Branch-D
----------------------------------------------------------
Pencil 20 15 32 8
Ruler 12 0 40 10
Staple 4 8 5 0
and so on...
How can I use query to call the above result and assign each sum to their respective branch column?
below is my query:
SELECT `Item`, `Branch`, sum(`Order_Quantity`) FROM `table` GROUP BY `Item`
but when I call and loop the table, the result will show sum quantity to every branches
Item Branch-A Branch-B Branch-C Branch-D
----------------------------------------------------------
Pencil 75 75 75 75
Ruler 62 62 62 62
Staple 17 17 17 17
Hope someone can help for this.
thanks.

Try:
SELECT `Item`, `Branch`, sum(`Order_Quantity`) FROM `table` GROUP BY `Item`, `Branch`

This is some kind of PIVOT:
select item,
sum(case when branch = 'Branch-A' then order_Quantity else 0 end) as BranchA,
sum(case when branch = 'Branch-B' then order_Quantity else 0 end) as BranchB,
sum(case when branch = 'Branch-C' then order_Quantity else 0 end) as BranchC,
sum(case when branch = 'Branch-D' then order_Quantity else 0 end) as BranchD
from yourTable
group by item

assuming you have a finite number of branches you can create a query with sub selects for each "column" you wish to display (as per branch) with your sums, like so...
select
(select sum(order_quantity) from table where branch = 'Branch-A'),
(select sum(order_quantity) from table where branch = 'Branch-B'),
etc..
This is not a very elegant solution, but it will result in what you're looking for.
Otherwise you can follow the advice of the other posters which is more efficient from a sql standpoint but will not generate the columns you are hoping to see (as per your question).

SELECT SUM(Order_Quantity) AS CNT FROM `table` GROUP BY `Branch`;

Related

Merging rows in SQL

My table looks like this:
Dept Wk1 Wk2
100 25 50
200 25 50
300 25 50
400 25 50
500 25 50
My results need to look like this:
Dept Wk1 Wk2
100 25 50
200 25 50
300 25 50
400 50 100
Things worth noting; the database is Pervasive PSQL10 and I'm using PHP to handle the results. I thought about doing this merge in PHP, but ideally if it could be done in the query that would save me the need for the extra code.
Reason for combining rows is that 2 depts will be treated as one when the data is pulled.
I think I'm overthinking it, but I've explored union, group by, and stuff (which I'm probably using incorrectly) and nothing is giving me what I need.
Any help or direction would be greatly appreciated, because what I've read so far addresses rows that have the same values, but not different.
Here is what my query actually looks like:
SELECT
dept_workcenter,
SUM(case when right(date_sequence,2) between 0 and 7 then hours_worked else 0 end) as wk1,
SUM(case when right(date_sequence,2) between 8 and 14 then hours_worked else 0 end) as wk2,
SUM(case when right(date_sequence,2) between 15 and 21 then hours_worked else 0 end) as wk3,
SUM(case when right(date_sequence,2) between 22 and 28 then hours_worked else 0 end) as wk4,
SUM(case when right(date_sequence,2) between 29 and 31 then hours_worked else 0 end) as wk5
FROM job_detail
WHERE job between '017079' AND '017207'
AND date_sequence BETWEEN '141200' and '141231'
AND dept_workcenter != ''
GROUP BY dept_workcenter
HAVING SUM(hours_worked) <> '0'
AND SUM(hours_worked) > '0.05';
You can use a case statement in the group by:
select (case when dept in (400, 500) then 400 else dept end) as dept,
sum(wk1) as wk1, sum(wk2) as wk2
from table t
group by (case when dept in (400, 500) then 400 else dept end)
order by dept;
So basically take the 500 and merge it with the 400?
SELECT Dept, SUM(Wk1) AS Wk1, SUM(Wk2) AS Wk2
FROM yourtable
GROUP BY Dept IN (400,500), Dept
This is not an uncommon problem in reporting. The typical method to handle this is to generate a temporary table in which you can modify the 500 to be 400, and then do a GROUP BY and SUM. This method will become more useful the more complicated your reporting becomes over time.
create table #DeptReptTable from select * from department;
update #DeptReptTable set Dept = 400 where Dept = 500;
select Dept, SUM(Wk1) Wk1, SUM(Wk2) Wk2 from #DeptReptTable group by Dept
drop table #DeptReptTable
Note: The # in front of the temp table is a Sybase-ism, which will create a table tied to the current SQL connection / session. I don't know if that magic works for Pervasive.

Select max win series: sql query

MySQL
I have table, where i store user_matches and it result:
n_match id_user id_score
1 55 1
1 66 0
This mean, 'user with id=55 win match with id=1 to user with id=66'.
So, we have 10, 100, 1000 matches, where user win or lose to opponents:
n_match id_user id_score
1 55 1 (win)
1 66 0
2 55 0 (lose)
2 77 1
3 55 1 (win)
3 77 0
4 55 1 (win)
4 77 0
5 55 1 (win)
5 77 0
Ok. As u can see, user win 3 matches without losing (win series)- and that's what i need from my query.
Question: How could i get from this table the longest series of won matches? Is it possible without looping on sql side or server side- just from query?
Thx.
Edit: One of solution i just now understand,- to get all matches as string like 001010101111010101011, then split it into array of strings with separator '0' -> [1, 1, 1, 1111, ...] and just take the longest string length.
But in this case i have to write server side code =\ That's not good, but mb the fastest.
The best way to do this is to calculate the cumulative number of losses for any match. For a sequence of wins, this value is constant. You can then use group by to get the length of the longest such sequence.
This version of the query is database-neutral. It uses subqueries to get the counts:
select user_id, max(NumWinsInRow)
from (select user_id, cumlosses, count(*)-1 as NumWinsInRow
from (select m.*,
(select sum(case when id_score = 0 then 1 else 0 end) from user_matches m2 where m2.id_user = m.id_user and m2.n_match <= m.n_match
) as CumLosses
from user_matches m
) t
group by cumlosses, user_id
) t
group by user_id
This query should run faster if you have an index on user_matches(id_user, n_math, id_score).

PHP MySQL: Take highest values from multiple categories and write an array?

I have a table of student scores. Students can take the test multiple times, we only care about the highest score.
So the table looks something like this:
UserID CatID Score
20 5 60
20 5 85
20 5 80
20 6 90
20 7 80
20 7 75
20 7 90
22 5 75
22 5 85
Want to get back one row based on a UserID variable that looks like this:
UserID Cat5 Cat6 Cat7
20 85 90 90
Here's what I'm using so far as a query:
SELECT score AS Score
, catid
FROM `quiz_result`
WHERE userid=65 and catid=5
ORDER BY score DESC
LIMIT 0, 1
Not sure how to get the other categories in one row...thoughts?
Thanks!
Try this piece:
SELECT catID, MAX( score ) FROM `quiz_result`
GROUP BY catID;
The output isn't exactly same as in your sample, but it pretty much gives what you need.
EDIT
Output will be like:
catID MAX(score)
Cat5 85
Cat6 90
Cat7 90
To get other columns, just include their names in the SELECT query.
Try this :
SELECT CONCAT_WS(',', catID) AS catID, CONCAT_WS(',', MAX(score)) FROM `quiz_result` GROUP BY catID;

SUM acorrding to another column

I need to know if there is a possible way doing this with out subquery..
Here is my table structure:
id-name-father_id
1 joe 0
2 mark 0
3 muller 0
4 miki 2
5 timi 2
6 moses 2
7 david 1
8 momo 0
9 daniel 0
10 ermi 3
My table logic is
0 means he is not a child of some one
1+ mean that he is son of man in that row.
Note: if some one have a child, he still
will have 0 in father id (it's mean there is not grand-fathers in my table)
My query is :
SELECT id, name, count(id=father_id) as sons
WHERE father_id = 0
What I want to get is a list of non-children (father_id=0) and sum
the childrens it has.
Is there a way to get the results without a subquery?
This should do it (MySQL):
SELECT `parents`.`id`, `parents`.`name`, COUNT(`children`.*) AS sons
FROM `people` AS parents
LEFT JOIN `people` AS children ON `parents`.`id` = `children`.`father_id`
WHERE `parents`.`father_id` = 0
GROUP BY `parents`.`id`
According to Gary we need to add name to GROUP BY in other SQL databases:
SELECT `parents`.`id`, `parents`.`name`, COUNT(`children`.*) AS sons
FROM `people` AS parents
LEFT JOIN `people` AS children ON `parents`.`id` = `children`.`father_id`
WHERE `parents`.`father_id` = 0
GROUP BY `parents`.`id`, `parents`.`name`
We are joing the table with itself here. So we join all parents with their children.
This will lead to a result like that:
parents.id parents.name children.id children.name
1 joe 7 david
2 mark 4 miki
2 mark 5 timi
2 mark 6 moses
3 muller 10 ermi
8 momo - - # left join allows this line
9 daniel - -
But now we have each parent several times. So we are GROUP'ing the whole thing over the parent’s id, which will result in the following:
parents.id parents.name COUNT(children.*)
1 joe 1
2 mark 3
3 muller 1
8 momo 0
9 daniel 0
You should be able to do it without any joins or sub-queries as follows:
select case father_id when 0 then id else father_id end id,
max(case father_id when 0 then name end) name,
sum(sign(father_id)) sons
from table
group by case father_id when 0 then id else father_id

summing two columns total in mysql

I want a resultset for this table:
ID Number_of_posts Number_of_user
1 100 21
2 23 34
as
ID Number_of_posts Number_of_user Number_of_posts_AND_Number_of_user
1 100 21 178
2 23 34 178
-----------------------------------------------
123 55
Is it possible to get the sum of two colums as another column/ as output in mysql?
To get cross-tab totals (horizontal and vertical):
select id,
number_of_posts as p,
number_of_users as u,
number_of_posts+number_of_users as p_and_u
from tbl
union all
select 99999 as id,
sum(number_of_posts) as p,
sum(number_of_users) as u,
sum(number_of_posts+number_of_users) as p_and_u
from tbl
order by 1
This will give you:
id p u p_and_u
----- --- --- -------
1 100 21 121
2 23 34 57
99999 123 55 178
You're complicating your query needlessly and using more memory that you have to. Pull the records in one query, then make another query to get the aggregates.
I know it doesn't answer your question, but it's what you should be doing instead. =)
SELECT id, number_of_posts, number_of_user,
(
SELECT SUM(number_of_posts + number_of_user)
FROM mytable
)
FROM mytable
SELECT SUM(Number_of_posts), SUM(Number_of_user) FROM table;
SELECT *,
(SELECT SUM(Number_of_posts) + SUM(Number_of_user) FROM TABLE) AS total
FROM table;
(Edit: Didn't originally notice it was the total total in the last column.)
Does MySQL support ROLLUP?
SELECT id,
SUM(Number_of_posts) Number_of_posts,
SUM(Number_of_user) Number_of_user,
SUM(Number_of_posts) + SUM(Number_of_user) Number_of_posts_AND_Number_of_user
FROM table
GROUP BY ROLLUP(id)
Edit: based on a quick search, in MySQL the last line might be GROUP BY id WITH ROLLUP.

Categories