MySQL Sum and Case Query - mysql

I create a ReportViewer with VB.NET connecting to a MySQL database. The data appears like below.
IdProduct Quantity TotalPrice OrderDate
0001 1 10 29/09/2014
0002 2 40 29/09/2014
0001 4 40 29/09/2014
0001 2 20 29/09/2014
0001 2 20 29/09/2014
Based on the records above, I'd like the result to appear like below
0001 0002
9 2
90 40
What is Query Sum Case the best use here? Thanks in advance.

NOTE: It's not possible for a query to "dynamically" alter the number or datatype of the columns returned, those must be specified at the time the SQL text is parsed.
To return the specified resultset with a query, you could do something like this:
SELECT SUM(IF(t.IdProduct='0001',t.Quantity,NULL)) AS `0001`
, SUM(IF(t.IdProduct='0002',t.Quantity,NULL)) AS `0002`
FROM mytable t
UNION ALL
SELECT SUM(IF(t.IdProduct='0001',t.TotalPrice,NULL)) AS `0001`
, SUM(IF(t.IdProduct='0002',t.TotalPrice,NULL)) AS `0002`
FROM mytable t
Note that the datatypes returned by the two queries will need to be compatible. This won't be a problem if Quantity and TotalPrice are both defined as integer.
Also, there's no specific guarantee that the "Quantity" row will be before the "TotalPrice" row; we observe that behavior, and it's unlikely that it will ever be different. But, to have a guarantee, we'd need an ORDER BY clause. So, including an additional discriminator column (a literal in the SELECT list of each query), that would give us something we could ORDER BY.
Note that it's not possible to have this single query dynamically create another column for IdProduct '0003'. We'd need to add that to the SELECT list of each query.
We could do this in two steps, using a query to get the list of distinct IdProduct, and then use that to dynamically create the query we need.
BUT... with all that said... we don't want to do that.
The normative pattern would be to return Quantity and TotalPrice as two separate columns, along with the IdProduct as another column. For example, the result returned by this statement:
SELECT t.IdProduct
, SUM(t.Quantity) AS `Quantity`
, SUM(t.TotalPrice) AS `TotalPrice`
FROM mytable t
GROUP BY t.IdProduct
And then the client application would be responsible for transforming that resultset into the desired display representation.
We don't want to push that job (of transforming the result into a display representation) into the SQL.

select idproduct, sum(quantity), sum(totalprice)
from your_table
group by idproduct

Related

Get the sum of the numbers generated by sql

I have a table named Company which has categorized by several sector_id
SELECT sector_id,count(sector_id) FROM Company group by sector_id
I could get the company numbers like this
sector_id count(sector_id)
1 10
2 15
3 22
Then, I would like to get the sum of count(sector_id) 10 + 15 + 22
Is it possible to do this by sql only? or I need to make some code with php??
Just remove the group by:
SELECT count(*)
FROM Company ;
EDIT:
It occurs to me that you want a summary row as well as the original data. If so, you can use rollup or grouping sets in most databases. Something like this:
SELECT sector_id, count(sector_id)
FROM Company
GROUP BY sector_id WITH ROLLUP;
Yes, it is possible to calculate sum using sql by using SUM() method
Syntax :
SELECT SUM(column_name)
FROM Table_Name;
In your case it will be like this :
SELECT SUM(sector_id)
FROM Company ;
Hope it helps.

MYSQL find max value

Take a MYSQL table like this :
id:prod1, priceA:10, priceB:20, priceC:30,priceD:18,...
id:prod2, priceA:22, priceB:20, priceC:30,priceD:78,...
id:prod3, priceA:4, priceB:20, priceC:30,priceD:19,...
I'm trying to select all ids where priceA is the lowest of the 3 prices, in this case, prod1 and prod3
I have tried to use max() but it acts only on one field.
I was thinking of something along the lines of :
SELECT id from table WHERE priceA < priceB AND priceA < priceC..., but in real life, there's 20 prices columns so it's highly unpractical...
Could anyone tell me if there is a function I don't know about that would simplify my query?
You can consider using the LEAST function. Still, you would have to list all the price columns, as below:
SELECT id
FROM table
WHERE priceA = LEAST(priceA, priceB, priceC);
Please see the SQL Fiddle.

Order number and strings putting strings last

I am trying to make a SQL statement that selects and orders numbers in DESC but put all strings last
so mysql is:
"SELECT * FROM posts ORDER BY price DESC"
and that gives me something like
test
best offer
6000
100
10
what I want is:
6000
100
10
test
best offer
or (doesnt matter)
6000
100
10
best offer
test
SELECT * FROM posts
ORDER BY price * 1 DESC
SQLFiddle demo
I think want you actually want is:
SELECT * FROM t ORDER BY value ASC;
which returns:
10
100
6000
best offer
test
SQL Fiddle
If you generally do not care about performance, you can do something like this:
SELECT * FROM posts
ORDER BY
CASE CAST(price AS int) WHEN 0 THEN ' ' ELSE price END DESC,
price ASC;
You might need the casts to int depending on your database.
You can also fiddle with the first expression to get the results you want. The point is that you have to sort first by whether it's a number or not and then the actual content.
The problem is that this you can't use any indexes this way. If you are allowed to change the database structure, it would be better to split the data into two columns. An int column with the price and a varchar column with the price description (in which case the first column is NULL). Then you can do faster queries.

Complex MySQL COUNT query

Evening folks,
I have a complex MySQL COUNT query I am trying to perform and am looking for the best way to do it.
In our system, we have References. Each Reference can have many (or no) Income Sources, each of which can be validated or not (status). We have a Reference table and an Income table - each row in the Income table points back to Reference with reference_id
On our 'Awaiting' page (the screen that shows each Income that is yet to be validated), we show it grouped by Reference. So you may, for example, see Mr John Smith has 3 Income Sources.
We want it to show something like "2 of 3 Validated" beside each row
My problem is writing the query that figures this out!
What I have been trying to do is this, using a combination of PHP and MySQL to bridge the gap where SQL (or my knowledge) falls short:
First, select a COUNT of the number of incomes associated with each reference:
SELECT `reference_id`, COUNT(status) AS status_count
FROM (`income`)
WHERE `income`.`status` = 0
GROUP BY `reference_id`
Next, having used PHP to generate a WHERE IN clause, proceed to COUNT the number of confirmed references from these:
SELECT `reference_id`, COUNT(status) AS status_count
FROM (`income`)
WHERE `reference_id` IN ('8469', '78969', '126613', ..... etc
AND status = 1
GROUP BY `reference_id`
However this doesn't work. It returns 0 rows.
Any way to achieve what I'm after?
Thanks!
In MySQL, you can SUM() on a boolean expression to get a count of the rows where that expression is true. You can do this because MySQL treats true as the integer 1 and false as the integer 0.
SELECT `reference_id`,
SUM(`status` = 1) AS `validated_count`,
COUNT(*) AS `total_count`
FROM `income`
GROUP BY `reference_id`

Mysql subquery with sum causing problems

This is a summary version of the problems I am encountering, but hits the nub of my problem. The real problem involves huge UNION groups of monthly data tables, but the SQL would be huge and add nothing. So:
SELECT entity_id,
sum(day_call_time) as day_call_time
from (
SELECT entity_id,
sum(answered_day_call_time) as day_call_time
FROM XCDRDNCSum201108
where (day_of_the_month >= 10 AND day_of_the_month<=24)
and LPAD(core_range,4,"0")="0987"
and LPAD(subrange,3,"0")="654"
and SUBSTR(LPAD(core_number,7,"0"),4,7)="3210"
) as summary
is the problem: when the table in the subquery XCDRDNCSum201108 returns no rows, because it is a sum, the column values contain null. And entity_id is part of the primary key, and cannot be null.
If I take out the sum, and just query entity_id, the subquery contains no rows, and thus the outer query does not fail, but when I use sum, I get error 1048 Column 'entity_id' cannot be null
how do I work around this problem ? Sometimes there is no data.
You are completely overworking the query... pre-summing inside, then summing again outside. In addition, I understand you are not a DBA, but if you are ever doing an aggregation, you TYPICALLY need the criteria that its grouped by. In the case presented here, you are getting sum of calls for all entity IDs. So you must have a group by any non-aggregates. However, if all you care about is the Grand total WITHOUT respect to the entity_ID, then you could skip the group by, but would also NOT include the actual entity ID...
If you want inclusive to show actual time per specific entity ID...
SELECT
entity_id,
sum(answered_day_call_time) as day_call_time,
count(*) number_of_calls
FROM
XCDRDNCSum201108
where
(day_of_the_month >= 10 AND day_of_the_month<=24)
and LPAD(core_range,4,"0")="0987"
and LPAD(subrange,3,"0")="654"
and SUBSTR(LPAD(core_number,7,"0"),4,7)="3210"
group by
entity_id
This would result in something like (fictitious data)
Entity_ID Day_Call_Time Number_Of_Calls
1 10 3
2 45 4
3 27 2
If all you cared about were the total call times
SELECT
sum(answered_day_call_time) as day_call_time,
count(*) number_of_calls
FROM
XCDRDNCSum201108
where
(day_of_the_month >= 10 AND day_of_the_month<=24)
and LPAD(core_range,4,"0")="0987"
and LPAD(subrange,3,"0")="654"
and SUBSTR(LPAD(core_number,7,"0"),4,7)="3210"
This would result in something like (fictitious data)
Day_Call_Time Number_Of_Calls
82 9
Would:
sum(answered_day_call_time) as day_call_time
changed to
ifnull(sum(answered_day_call_time),0) as day_call_time
work? I'm assuming mysql here but the coalesce function would/should work too.