Multiple aggregate functions in one SQL query from the same table using different conditions
SELECT
E.EMPID
,SUM(ABSENCE.HOURS_ABSENT) AS ABSENT_TOTAL
,SUM(case when year(Date) = 2010 then ABSENCE.HOURS_ABSENT else 0 end) AS ABSENT_YEAR
FROM
EMPLOYEE E
INNER JOIN ABSENCE ON
ABSENCE.EMPID = E.EMPID
GROUP BY
E.EMPID
HAVING
SUM(ATOTAL.HOURS_ABSENT) > 10
OR SUM(case when year(Date) = 2010 then ABSENCE.HOURS_ABSENT else 0 end) > 3
edit:
It's not a big deal, but I hate repeating conditions so we could refactor like:
Select * From
(
SELECT
E.EMPID
,SUM(ABSENCE.HOURS_ABSENT) AS ABSENT_TOTAL
,SUM(case when year(Date) = 2010 then ABSENCE.HOURS_ABSENT else 0 end) AS ABSENT_YEAR
FROM
EMPLOYEE E
INNER JOIN ABSENCE ON
ABSENCE.EMPID = E.EMPID
GROUP BY
E.EMPID
) EmployeeAbsences
Where ABSENT_TOTAL > 10 or ABSENT_YEAR > 3
This way, if you change your case condition, it's in one spot only.
Multiple aggregate functions in SQL query
Never use commas in the FROM
clause. Always use proper, explicit, standard JOIN
syntax.
Next, learn what COUNT()
does. It counts the number of non-NULL values. So, your expressions are going to return the same value -- because f.UID
and s.UID
are never NULL
(due to the JOIN
conditions).
The issue is that the different dimensions are multiplying the amounts. A simple fix is to use COUNT(DISTINCT)
:
SELECT p.ID, COUNT(DISTINCT s.UID) AS SubCount, COUNT(DISTINCT f.UID) AS FollowCount
FROM page p JOIN
subs s
ON p.ID = s.ID JOIN
followers f
ON s.ID = f.ID
GROUP BY p.ID;
The inner joins are equivalent to the original query. You probably want left join
s so you can get counts of zero:
SELECT p.ID, COUNT(DISTINCT s.UID) AS SubCount, COUNT(DISTINCT f.UID) AS FollowCount
FROM page p LEFT JOIN
subs s
ON p.ID = s.ID LEFT JOIN
followers f
ON p.ID = f.ID
GROUP BY p.ID;
Optimal SQL to perform multiple aggregate functions with different group by fields
Is it slow because it's evaluating each row separately with the subquery in the select statement? It may be operating as a correlated subquery.
If that's the case it might be faster if you get the values out of a join and go from there -
Select city, t1.item, (COUNT(t1.item) / MAX(t2.it_count)) AS pen_ratio
from records t1
JOIN (SELECT item, count(item) AS it_count
FROM records
group by item) t2
ON t2.item = t1.item
GROUP BY city, t1.item
Updated some errors and included the fiddle based off the starting point from xQbert. I had to CAST as float in the fiddle, but you may not need to CAST and use the above query in yours depending on datatypes.
I believe this follows the intent of your original query.
https://dbfiddle.uk/?rdbms=postgres_13&fiddle=d77a715175159304b9192a16ad903347
SQL Filter two aggregate functions with different conditions
You can use conditional aggregation:
SELECT airline_name,
(AVG(CASE WHEN fl_date BETWEEN '2017-07-24' and '2017-07-31' THEN arr_delay_new END) -
AVG(CASE WHEN fl_date BETWEEN '2017-07-01' and '2017-07-23' THEN arr_delay_new END)
) as AVG_DIFF
FROM Flight_delays F JOIN
Airlines A
ON A.airline_id = F.airline_id
GROUP BY airline_name;
This assumes that arr_delay_new
has a type that can be averaged. Some databases are reluctant to do averages on date/times directly.
Combining two or more different SELECT queries to same table with different conditions in PostgreSQL
Just write this as one query:
select sum(price) as lucro_esperado, count(*) as tarefas_abertas
from tasks
where extract(month from enddate) = 12 and
extract(year from enddate) = 2019
I would advise you to change the where
clause to:
where enddate >= '2019-12-01' and
enddate < '2020-01-01'
This allows the database to use an index on enddate
(if available). Also, removing the function calls on the column helps the optimizer.
EDIT:
I see, the two date parameters are different. Just use conditional aggregation:
select sum(case when enddate >= '2019-12-01' and enddate < '2020-01-01' then price end) as lucro_esperado,
sum(case when date_added >= '2019-12-01' and date_added < '2020-01-01' then 1 else 0 end) as tarefas_abertas
from tasks;
multiple conditions on a sql Aggregate Function
Seems like you just need to add a , and the field name to the group by.
You may want to add identifier_two to the select as well in case the where clause needs to be updated to account for both identifiers. (Likely)
SELECT identifier_one
, identifier_two --not required but may be useful as you seem to filter on identifier_one later; maybe you also need the 2nd one...
, SUM(IF(YEAR(`date`) = YEAR(CURDATE()), quantity, 0)) AS current_year,
, SUM(IF(YEAR(`date`) = YEAR(CURDATE()) AND MONTH(`date`) = MONTH(CURDATE() ), quantity, 0)) AS current_month
, SUM(IF(YEAR(`date`) = YEAR(CURDATE()) - 1, quantity, 0)) AS last_year
, SUM(IF(YEAR(`date`) = YEAR(CURDATE()) AND MONTH(`date`) = MONTH(CURDATE()) - 1, quantity, 0)) AS last_month
FROM sales
GROUP BY identifier_one, identifier_two --this is what you're missing
SQL Query - How to apply different conditions (Where clause?) to specific aggregated columns
Using conditional aggregation, which in most databases looks like this:
SELECT Test,
SUM(CASE WHEN TESTSTATUS = 'P' THEN TESTPRICE END) AS PendingRev,
SUM(CASE WHEN TESTSTATUS = 'S' THEN TESTPRICE END) AS StartedRev
FROM REQUEST
GROUP BY TEST
ORDER BY TEST;
Can we use same aggregate function more than once on same table field or column using Different filter conditions?
You can use an aggregate function with a CASE
:
SELECT Date1,
CC,
BU,
SUM(case when mode = '011' then Amount end) Mode011,
SUM(case when mode = '012' then Amount end) Mode012,
SUM(case when mode = '013' then Amount end) Mode013,
SUM(case when mode = '014' then Amount end) Mode014
FROM MainTable
GROUP BY CC,BU,Date1;
Or you can use the PIVOT function:
select date1, CC, BU,
[011] Mode011,
[012] Mode012,
[013] Mode013,
[014] Mode014
from
(
select date1, CC, BU, mode, amount
from maintable
) src
pivot
(
sum(amount)
for mode in ([011], [012], [013], [014])
) piv
Aggregate on multiple conditions: convert to a single query
I prefer to have a query like this, because what if there are some places
that have no reservation
yet or may have multiple reservations already. Still it's safe to calculate the SUM
.
SELECT d.*, a.total_confirmed, b.total_paid, c.total_paid_unconfirmed
FROM places d
LEFT JOIN
(
SELECT places.id, places.name, COUNT(reservations.*) as total_confirmed
FROM reservations
INNER JOIN places ON places.id = reservations.place_id
WHERE
reservations.confirmed_at IS NOT NULL
GROUP BY places.id, places.name
) a ON d.id = a.id
LEFT JOIN
(
SELECT places.id, places.name, COUNT(reservations.*) as total_paid
FROM reservations
INNER JOIN places ON places.id = reservations.place_id
WHERE
reservations.paid_at IS NOT NULL
GROUP BY places.id, places.name
) b ON d.id = b.id
LEFT JOIN
(
SELECT places.id, places.name, COUNT(reservations.*) as total_paid_unconfirmed
FROM reservations
INNER JOIN places ON places.id = reservations.place_id
WHERE
reservations.paid_at IS NOT NULL AND reservations.confirmed_at IS NULL
GROUP BY places.id, places.name
) c ON d.id = c.id
Related Topics
Saving Results with Headers in SQL Server Management Studio
When to Use an Auto-Incremented Primary Key and When Not To
How to Connect an Existing SQL Server Login to an Existing SQL Server Database User of Same Name
How to Manually Execute SQL Commands in Ruby on Rails Using Nuodb
Postgresql: Remove Attribute from JSON Column
Returning Month Name in SQL Server Query
Set Database from Single User Mode to Multi User
Find Duplicate Records in a Table Using SQL Server
SQL Column Definition: Default Value and Not Null Redundant
How Long Should SQL Email Fields Be
Sql-Server: Error - Exclusive Access Could Not Be Obtained Because the Database Is in Use
SQL Left Join First Match Only
SQL Query to Collapse Duplicate Values by Date Range
How to Find the Size of a Table in SQL