This question already has answers here:
SQL to add a summary row to MySQL result set
(4 answers)
Closed 4 years ago.
Is it possible to total two columns, however still show all of the results? At the moment, If i sum one of the columns in the select statement (e.g. sum(sales_amount), it only 1 line of the results show
SALES_ID EMPLOYEE_ID PRODUCT_ID SALES_AMOUNT QUANTITY DATE
1 123148 4578947 80 1 01/01/2018
2 123148 5124578 80 1 01/01/2018
I want to keep the two results shown above, however an extra line created showing a total of 160 under the sales_amount, quantity of 2.
This is arguably bad SQL because the semantics of the last row is different from the others. (Rows and columns should be logically interchangeable.) That said, as I write this, I see that #Gordon-Linoff has just given the answer that I was going to give. Still, I would argue that such aggregations should be separate.
The simplest way in this case probably union all:
select SALES_ID, EMPLOYEE_ID, PRODUCT_ID, SALES_AMOUNT, QUANTITY, DATE
from t
union all
select NULL, NULL, NULL, SUM(sales_amount), sum(quantity), date
from t
group by date;
If your data is the result of an aggregation query, then rollup would be appropriate.
Select SALES_ID, EMPLOYEE_ID, PRODUCT_ID,SALES_AMOUNT ,QUANTITY, DATE ,
(SALES_AMOUNT* QUANTITY) AS TOTAL FROM (YOUR TABLE NAME)
If you use this query, the amount is multiplied by the quantity for each row and displayed in the new column
Related
This question already has answers here:
How to select and/or delete all but one row of each set of duplicates in a table?
(2 answers)
How can I remove duplicate rows?
(43 answers)
Closed 1 year ago.
I've a flights table that consists of few columns but somebody seem to have ran a migration twice that resulted in creation of same data twice.
Anyway, the flight should only have only data from the following condition: The flight_number and the date.
Basically the table is looking like this at the moment:
flight_number
date
123
2021-09-16
123
2021-09-16
123
2021-09-17
124
2021-09-18
124
2021-09-18
Result I want:
flight_number
date
123
2021-09-16
123
2021-09-17
124
2021-09-18
Basically, keep only one and remove duplicated (if the flight_number is same of the same date).
I'm looking for a DELETE SQL query but couldn't find the one like I am looking for.
What is the query that can help me achieve it?
Thanks!
EDIT: Yes, all the data has a column id that is unique even if the data is same.
You need to identify which rows to keep and which to remove; this can be done as such:
delete ff from
flight ff
inner join (
select flight_number, row_number() over (partition by flight_number order by date) as RN
from flight f
) dups
on ff.flight_number = dups.flight_number
where dups.rn > 1
Basically, this uses Row_Number to create a row identifier based on certain criteria, in this case, for each (partition) Flight_number, create a row number then delete any records where the row_number is > 1.
You will need to change this to use the actual ID column on the join, like this https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=58a4ac7235ea22b557116ad68c8449c3
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
here is a screen shot of my table
I am trying to remove all those rows whose sum of PostAmt comes to be 0 when grouped by the sales_contract_nbr and the name.
for example :
the sales_contract_nbr 51101008103 will be removed when grouped by name and sales_contract_nbr as -96.83 and 96.83 when summed up amounts to 0.
Quite simple right?
but what I want apart from this is that I want to remove the contracts in group. I mean if the contract 51101008195 is grouped it amounts to be 533.87 which won't be removed (highlighted)
But I want to remove it in groups
for example
two rows of contract number 51101008195 should be summed first (see the image below) I mean the amount -533.87 and 533.87 should be summed to get the total of 0. Only one record for the contract should be left.
Update
More Description :
what i want to do is first group the row number 1 and 2 (matching amounts one positive and the other negative) and then group the others. If there were 4 rows of the same contract number then the row 1 and row 2 should have been grouped then the row 3 and row 4 should be grouped if there absolute amounts are same if not the row number 3 and 4 doesn't get deleted.
I want to use group by to eliminate the rows whose total ends up to be 0 and which have the same name or the contract number.
I hope I have made the question clear. If not please ask.
how can it be done?
what i am doing till now is :
SELECT sales_contract_nbr
,name
,SUM(PostAmt) PostAmt
FROM tblMasData
GROUP BY sales_contract_nbr, name
thanks.
Here is what I come up with for now :
SELECT location
,sales_contract_nbr
,name
,SUM(absPostAmt * nbPostAmt) / ABS(SUM(nbPostAmt)) PostAmt
,ABS(SUM(nbPostAmt)) nbPostAmt
,SUM(absPostAmt * nbPostAmt) PostAmtTotal
FROM (
SELECT location
,sales_contract_nbr
,name
,PostAmt
,ABS(PostAmt) absPostAmt
,SUM(CASE WHEN PostAmt >= 0 THEN 1 ELSE -1 END) nbPostAmt
FROM tblMasData
GROUP BY location
,sales_contract_nbr
,name
,PostAmt
,ABS(PostAmt)
) t
GROUP BY location
,sales_contract_nbr
,name
,absPostAmt
HAVING SUM(absPostAmt * nbPostAmt) != 0
See SQLFiddle.
This doesn't totally answer your question, as if you have 100 + 100 - 200 for instance, it won't hide all three rows. But it can be pretty messy to find combinations which equal to 0 among a bunch of rows.
More, if some rows have the same amount, they will be grouped. That's why I added a column counting those rows being equal, and a column summing them up at the end.
This should at least allow you to deal with the data programmatically.
Let me know if this fills your needs, or if you need some improvement (which could involve some not so pretty SQL).
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`
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.