0

Does SQL allow assigning the return of an aggregate function to another variable of the same type? I’m trying to take the Count(ID) of a table and assign the returned result to a temp table and my query continues to error with an ‘aggregate function error’ so I’m wondering if the return value of COUNT(ID) is able to be assigned to a variable?

SELECT Count(ID) From SomeTable

DECLARE @ttl INT 

SET @ttl = Count(ID)

I’d like to take this returned number, let’s say 500, and then assign it to an INT variable in a temp table

DECLARE @cnt INT = 0;                                   
DECLARE @startYear DATETIME = '2011-01-01 00:00:00.000' 
DECLARE @endYear DATETIME   = '2011-12-31 23:59:59.999' 
DECLARE @ttl INT                                

SELECT DATEPART(year, @startYear) AS [Year of Totals], COUNT(ID) AS [Total For Year], GETDATE() AS [DATE/TIME of RUN]  
FROM SomeTable
ORDER BY [Year of Totals]

    SET @cnt = @cnt + 1;                           
    SET @startYear = DATEADD(year, 1, @startYear);  
    SET @endYear = DATEADD(year, 1, @endYear);     
    SET @ttl = COUNT(ID);   --> Problem Points to this as Invalid column 'ID'

INSERT INTO TempYearlyResults (Year, Total_YEAR, Date_Time, Test_Data) VALUES (DATEADD(YEAR,-1, @startYear), @ttl, GETDATE(), 'Is this working')

Editing original post with more details - Pic For Reference:enter image description here

--Pseudocode BEGIN

-- Variable Declarations

-- Initialize counter to zero

--> EDIT this for the start year

--> EDIT this for that end of start year

-- Initialize for Total Counts for Year

-- Create A Temp Table to Drop Loop Data into

--WHILE the counter is less than the number of years being requested, run the following WHILE LOOP WHILE @cnt < 3 --> EDIT this for the complete number of years being requested BEGIN

-- SELECT the Year, Total Count for said Year, and Date/Time this run is being executed

-- Increment the counter to display the next year in the loop

-- Increment the Start Year to the next year

-- Increment the end of the start year

-- Set @ttl Variable equal to the Total For Year of each year

-- Populate the Temp Table with the results

-- Show the collected results in the Temp Table

-- Drop Table after populating to allow for creation next time

-- Pseudocode END

MB9
  • 73
  • 1
  • 6
  • 1
    Sounds like the actual error you are getting is *"Column '.....' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause"* which implies that you have another column in the `SELECT` or `ORDER BY` of your query which is not in the `GROUP BY` (you are not showing this in the above) and note that if there is no `GROUP BY` then there is an implied empty set `GROUP BY ()`. – Charlieface Mar 09 '22 at 03:05
  • Thanks for the comments @Charlieface, just posted more detail, I will look to the Order BY & Group BY as well. – MB9 Mar 09 '22 at 15:05
  • 1
    Yeah that query won't work because you have `[Year of Totals]` in the `ORDER BY`. Once the `GROUP BY` runs (conceptually) then any aggregated columns no longer exist, only the aggregations exist. And `ORDER BY` is after `GROUP BY` in [logical order of execution](https://stackoverflow.com/a/4596608/14868997). Also `COUNT(ID)` probably doesn't do what you think it does. It does not count distinct ID values (for that you would need `COUNT(DISTINCT ID)`) it only counts non-null rows – Charlieface Mar 09 '22 at 15:07
  • Thanks, appreciate the confirmation. I have dug around looking for a way syntactically do this and figured I was breaking some rule of logic. – MB9 Mar 09 '22 at 15:23
  • @Charlieface, could you tell me if utilizing a ‘Derived Table’ would work in this instance? – MB9 Mar 25 '22 at 00:23
  • It looks like your pseudo-code is over-complicated and you likely don't need a temp table at all, probably just a join with a calendar table. Sample data and expected results for that sample (*as text* not images) would help immensely, as your description is rather unclear. I would suggest making a new question, as significantly changing a question after someone has answered is frowned upon – Charlieface Mar 25 '22 at 00:51
  • So you probably need something along the lines of `SELECT y.Year, COUNT(*) FROM SomeTable t JOIN Years y ON t.SomeDate >= y.Date1Jan AND t.SomeDate < y.Next1Jan GROUP BY y.Year` – Charlieface Mar 25 '22 at 00:54

1 Answers1

1

try assigning the variable in the sql. @startYear and @EndYear should be used as Where filters and not part of the groupings

DECLARE @ttl INT 
SELECT @ttl=Count(distinct ID) From SomeTable

select @ttl

Try partitioning ids by Year then counting them

  SELECT distinct DATEPART(year, YourDate) AS [Year of Totals], 
     COUNT(ID) over(partition by DATEPART(year, YourDate) order by DATEPART(year, Date))  AS [Total For Year], 
     GETDATE() AS [DATE/TIME of RUN]  
FROM SomeTable

Try a Cursor, increment a counter variable and store the results in a temp table after each year changes.

declare c1  cursor for
    select ID, Datepart(year, theDate) Year from SomeTable ORDER BY Datepart(year, theDate);
open c1

FETCH NEXT FROM c1 INTO @ID,@Year;
declare @Counter as int=0
declare @PrevYear as int=0
WHILE @@FETCH_STATUS = 0  
    BEGIN
       set @Counter=@Counter+1
       if @Year<>@PrevYear then
            begin
                 print @Counter
                 set @Counter=0
            end
       set @PrevYear=@Year
       FETCH NEXT FROM c1 INTO @ID,@Year;
    END

close c1
deallocate c1
Golden Lion
  • 3,840
  • 2
  • 26
  • 35
  • Thanks, tried this as well, ```SELECT @ttl = COUNT (DISTINCT ID) FROM SomeTable;``` - Returns huge numbers that are not what the original query returns. – MB9 Mar 09 '22 at 15:26
  • 1
    you can also try using Count(ID) over(partition by DATEPART(year, date) order by DATEPART(year, date)) as CountID – Golden Lion Mar 09 '22 at 16:23
  • I tried this as well @Golden Lion, I'm definitely unable to get this by the COUNT(ID) as Charlieface indicated. – MB9 Mar 09 '22 at 21:25
  • go to a simple count and group by sql. see if the counts are reasonable otherwise check for database corruption – Golden Lion Mar 09 '22 at 22:11
  • I tried this as well during the conversation with @Charlieface. This won’t work. Don’t believe any corruption exists as the per year COUNTS return fine. It’s the inserting the returned values into the temp table (shown in screenshot attached) that is not working. – MB9 Mar 09 '22 at 23:10
  • 1
    create a temp table and use a cursor to load counts by year. – Golden Lion Mar 09 '22 at 23:14
  • I was just reading about this, I’ve never done a cursor before so I will need to dig into that a bit, but that seems to be the best option. – MB9 Mar 09 '22 at 23:22
  • Don't think this will work because I'm using a @cnt variable in a WHILE loop to move to the next year in the SELECT statement. – MB9 Mar 10 '22 at 15:12
  • will you psuedo code your rules? I don't understand the patterns in your output – Golden Lion Mar 10 '22 at 15:16
  • Just edited original Post with Pseudo to show the WHILE LOOP I was originally trying to use, and basically trying to remove that Loop and implement a cursor. – MB9 Mar 10 '22 at 16:56
  • remove all your variables and get the aggregation to work with sql only – Golden Lion Mar 11 '22 at 16:20
  • Aggregations work without issue, the problem is getting the aggregation for each loop sequence into the TempTable. The screenshot shows all 3 years of the aggregate totals for years (2011, 2012, 2013). It's the TempTable on the bottom of the screenshot that has all the 4920420 numbers for each year that isn't working. – MB9 Mar 12 '22 at 02:08
  • aggregate with a sql using the cursor then create another query in the cursor loop and get the count then store the count in a temp table. – Golden Lion Mar 12 '22 at 13:43