Reputation: 3969
I'm using the following query to return the ages (in years) of all stored user date of births. It would be useful if I could essentially tally the ages so I could generate a report. The query is chunky and therefore makes it very difficult for me to understand how I'd do this, especially since aggregate functions cannot be assigned aliases.
Select
DateDiff(YEAR, dob, CURRENT_TIMESTAMP) -
CASE WHEN
DATEADD(year,DateDiff(YEAR, dob, CURRENT_TIMESTAMP),CURRENT_TIMESTAMP)
> CURRENT_TIMESTAMP
THEN 1
ELSE 0 END as ageYears
from [database].[dbo].[users]
Using the distinct
keyword I can return the age groups, not the instances, but how would I join these with a count
?
This output would be ideal:
age | numUsers
18 | 1
19 | 3
20 | 7
21 | 1
22 | 9
23 | 2
Upvotes: 0
Views: 64
Reputation: 69524
Test Data
DECLARE @T TABLE (ID INT, DOB DATE)
INSERT INTO @T
VALUES (1, '1940-01-01'),(2, '1940-01-01'),(3, '1985-01-01')
,(4, '1985-01-01'),(1, '1999-01-01'),(1, '1968-01-01')
Query
SELECT DateDiff(YEAR, dob, CURRENT_TIMESTAMP) -
CASE WHEN
DATEADD(year,DateDiff(YEAR, dob, CURRENT_TIMESTAMP),CURRENT_TIMESTAMP)
> CURRENT_TIMESTAMP
THEN 1
ELSE 0 END AS Age , COUNT(*) AS Total
FROM @T
GROUP BY DateDiff(YEAR, dob, CURRENT_TIMESTAMP) -
CASE WHEN
DATEADD(year,DateDiff(YEAR, dob, CURRENT_TIMESTAMP),CURRENT_TIMESTAMP)
> CURRENT_TIMESTAMP
THEN 1
ELSE 0 END
Result
╔═════╦═══════╗
║ Age ║ Total ║
╠═════╬═══════╣
║ 14 ║ 1 ║
║ 28 ║ 2 ║
║ 45 ║ 1 ║
║ 73 ║ 2 ║
╚═════╩═══════╝
Upvotes: 1
Reputation: 3516
Can you try this,
Select X.age, sum (X.num) numUsers
From (
Select
DateDiff(YEAR, dob, CURRENT_TIMESTAMP) -
CASE WHEN
DATEADD(year,DateDiff(YEAR, dob, CURRENT_TIMESTAMP),CURRENT_TIMESTAMP)
> CURRENT_TIMESTAMP
THEN 1
ELSE 0 END age,
1 num
from [database].[dbo].[users]
) X
group by X.age
Upvotes: 2
Reputation: 239694
Just use a CTE or subquery to create the ages first, and then a simple group by query to tally them up:
; With Ages as (
Select
DateDiff(YEAR, dob, CURRENT_TIMESTAMP) -
CASE WHEN
DATEADD(year,DateDiff(YEAR, dob, CURRENT_TIMESTAMP),CURRENT_TIMESTAMP)
> CURRENT_TIMESTAMP
THEN 1
ELSE 0 END as ageYears
from [database].[dbo].[users]
)
SELECT ageYears,COUNT(*) as NumUsers
FROM Ages
GROUP BY ageYears
The alternative, that doesn't need the subquery or CTE is to repeat the entire complex expression in the GROUP BY clause:
Select
DateDiff(YEAR, dob, CURRENT_TIMESTAMP) -
CASE WHEN
DATEADD(year,DateDiff(YEAR, dob, CURRENT_TIMESTAMP),CURRENT_TIMESTAMP)
> CURRENT_TIMESTAMP
THEN 1
ELSE 0 END as ageYears,
COUNT(*) as numUsers
from [database].[dbo].[users]
group by
DateDiff(YEAR, dob, CURRENT_TIMESTAMP) -
CASE WHEN
DATEADD(year,DateDiff(YEAR, dob, CURRENT_TIMESTAMP),CURRENT_TIMESTAMP)
> CURRENT_TIMESTAMP
THEN 1
ELSE 0 END as ageYears
Personally, I prefer the former version.
Upvotes: 2