MYSQL Group By Query with subtract of number based on where condition - mysql

i have One transaction table ( "TableA" ), In TableA have those fields app_id, user_id, points, tr_type, description. so in the transaction have added and subtract tr_type is there. now I want to get total_points (points = added-subtract) of the user_id based on tr_type. For that how I need to write MySQL query>
For type is either add or sub.
So now I want GroupBY of those 3 fields --> app_id, user_id, points

I suspect you want conditional aggregation:
select user_id,
sum(case when tr_type = 'add' then points
when tr_type = 'sub' then - points
end)
from t
group by user_id;

Related

Second ORDER BY criteria, how to restrict it to one value only?

I have hard time to design a proper SQL request, I need to select and order (ascending) "scores" summed up over several dates (here 2 dates), and WHEN EQUALITY, I need to order the scores according to one date only.
Here is what I have tried so far:
SELECT SUM(score)
FROM TABLE1
WHERE planning_date = "2021/09/16" AND planning_date = "2021/09/15"
ORDER BY SUM(score), SUM(score (BUT only for the case of planning_date = "2021/09/16")) )
Any idea ?
Thank you in advance
AND should be OR if you want to return results for two different dates. You can also use IN to match a list of dates.
Use a CASE expression inside SUM() to restrict the sum to a particular date.
SELECT SUM(score)
FROM TABLE1
WHERE planning_date IN ("2021/09/16", "2021/09/15")
ORDER BY SUM(score), SUM(CASE WHEN planning_date = "2021/09/16" THEN score END)

How would I group by all the fields except one so that I can remove duplicates?

This is my query.
select trackingbatches.batchnumber, requireddate, jobno, frames.frame_id, frame_no, groupdesc, finishdesc, finish2desc, BOUGHTINFRAME, NAME, MAX(statustimestamp) from JOBQUOTEHEADER
right join trackingbatches on JOBQUOTEHEADER.header_id=trackingbatches.header_id
right join frames on trackingbatches.header_Id=frames.header_id
right join trackingstagesettings on trackingbatches.status=trackingstagesettings.stage_id
where requireddate between current_date-1 and current_date
GROUP BY 1,2,3,4,5,6,7,8,9,10
ORDER BY JOBNO
However, I do not want to group by 'name'. I want it to select the latest 'statustimestamp' but as of now, it groups by name also so it gives me a row which is the same frame with all the same details but multiple occurrences of it in the factory. name refers to the stage of the frame in our factory.
BATCHNUMBER
REQUIREDDATE
JOBNO
FRAME_ID
FRAME_NO
GROUPDESC
FINISHDESC
FINISH2DESC
BOUGHTINFRAME
NAME
STATUSTIMESTAMP
5079
01.09
5STAR1
1
1
INT CASEMENT
STD WHITE
N/A
0
CUT
16.08.2021
5079
01.09
5STAR1
1
1
INT CASEMENT
STD WHITE
N/A
0
LOADED
02.09.2021
So as you can see from the two records above. That is the same frame but i only want one instance of it to show in my results, the instance of the latest status of it which is the second one that is 'LOADED' as its status with the field called name. So i want the max status timestamp for the latest instance of the frame but because it groups by the field 'name' as well, i can't get just the latest instance by itself.
You can create a rank on your current query (when you see duplicates) something like the following:
Rank will create a row number for each row per batchnumber in the desc order for date
Once the rank is created you can just filter = 1 to get the data per batchnumer in desc order based on statustimestamp
This way you don't need to worry about NAME GROUP BY as it it will not be in the partition by clause of the ROW_NUMBER() [which is creating the rank based on just batchnumber -- you can adjust it by adding more columns if you need something else to aggregate by]
WITH data AS (
select trackingbatches.batchnumber, requireddate, jobno, frames.frame_id, frame_no, groupdesc, finishdesc, finish2desc, BOUGHTINFRAME, NAME, MAX(statustimestamp) from JOBQUOTEHEADER
right join trackingbatches on JOBQUOTEHEADER.header_id=trackingbatches.header_id
right join frames on trackingbatches.header_Id=frames.header_id
right join trackingstagesettings on trackingbatches.status=trackingstagesettings.stage_id
where requireddate between current_date-1 and current_date
GROUP BY 1,2,3,4,5,6,7,8,9,10
ORDER BY JOBNO
),
rank_data_by_date AS
SELECT
*
,
ROW_NUMBER() OVER(PARTITION BY BATCHNUMBER ORDER BY STATUSTIMESTAMP DESC) AS RANK_
)
SELECT * FROM rank_data_by_date WHERE RANK_ = 1

Nested Select Queries that Group By Similar Field

I have a database of Time Entries which stores userID, roundedHours, dateSpent, and taskID for each entry (these are daily timecards). I am trying to create one query that will output sums of roundedHours grouped by userID where the taskID meets a specific value between specified dates.
The code I've attempted is below. I need it to be output and grouped by userID but instead, my output is the total sum for both overhead_admin and total_hours (same on each row) and not specific to the userID.
SELECT userName, userID,
(SELECT sum(roundedHours)
FROM `db`.`TimeEntries`
WHERE taskId = 3050483 AND (spendDate BETWEEN '2020-11-02' AND '2020-11-08')) as overhead_admin,
(SELECT sum(roundedHours)
FROM `db`.`TimeEntries`
WHERE (spendDate BETWEEN '2020-11-02' AND '2020-11-08')) as total_hours
FROM `db`.`TimeEntries`
GROUP BY userID
Can anyone help me so that each row will have the total SPECIFIC to that user and NOT summed as a whole? The output I'm getting that is wrong is shown in the image below:
Use conditional aggregation:
SELECT userName, userID,
sum(case when taskId = 3050483 AND (spendDate BETWEEN '2020-11-02' AND '2020-11-08' then roundedHours end) as overhead_admin,
sum(case when spendDate BETWEEN '2020-11-02' AND '2020-11-08' then roundedHours end) as total_hours
FROM `db`.`TimeEntries`
GROUP BY userID

How To Find Duplicate, Count and Sum Values from different columns in MySQL?

I have my table
I want to get duplicates from the Name and Status column, count them, and sum values from the Sum column. I want to look like this:
I am new to SQL so that it may be an easy answer, but I can't seem to find a solution.
This is how far I got, but I can't seem to get the count and sum without errors.
SELECT name, COUNT(*) AS recovered
FROM complaints
WHERE status = "Recovered"
GROUP BY name
HAVING COUNT(name) > 0
myQuery
You can do conditional aggregation:
select
name,
sum(status = 'Recovered') recovered,
sum(status = 'Unrecovered') unrecovered,
sum(case when status = 'Recovered' then `sum` end) total_recovered_value,
sum(case when status = 'Unrecovered' then `sum` end) total_unrecovered_value
from mytable
group by name
order by name
Side note: sum is a language keyword, hence not a good choice for a column name.

How to count the amount of rows being summed inside an SQL SUM function?

Here's a certain part of my SQL query:
SELECT pir.paymentInstrumentItemID AS id,
SUM(pir.priceChange) AS priceSum,
pir.clientInfoID AS clientID,
IFNULL(SUM(pir.costChange), 0) AS selfPrice,
pir.paymentInstrumentItemID
FROM paymentInstrumentRegister as pir
GROUP BY pir.paymentInstrumentItemID
What I need to do is to count the amount of rows that got grouped by inside the first SUM function and make a CASE statement out of it, so something like that:
SUM(CASE WHEN amtRows = 1 THEN 0 ELSE pir.priceChange) as priceSum
So basically whenever there is a single row I don't need the value, but as long as there's two or more of those, I need their sum.
Will appreciate feedback.
I think the best option is to add COUNT() to query, and let programming language to do the rest, but if you really need do that by MySQL:
SELECT
id,
(CASE WHEN amtRows = 1 THEN 0 ELSE priceSum) as priceSum,
amtRows,
clientID,
selfPrice,
paymentInstrumentItemID
FROM (
SELECT
pir.paymentInstrumentItemID AS id,
SUM(pir.priceChange) AS priceSum,
COUNT(pir.priceChange) as as amtRows,
pir.clientInfoID AS clientID,
IFNULL(SUM(pir.costChange),0) AS selfPrice,
pir.paymentInstrumentItemID
FROM
paymentInstrumentRegister as pir
GROUP BY
pir.paymentInstrumentItemID
) tmp