Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
silver_surfer21
Starting Member
21 Posts |
Posted - 2011-03-08 : 07:06:28
|
I have a function which I'm using to examine the number of houses sold in a month, and if its less than ten group it in with the next month until the total is greater than ten, before finding an average price across all the months.USE [MyHousePrice]GO/****** Object: UserDefinedFunction [dbo].[ExtendedMonthsCreation] Script Date: 03/08/2011 11:33:17 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER FUNCTION [dbo].[ExtendedMonthsCreation](@NoSoldInMonth int, @InitialMonth int, @InitialYear int,@currentHouseType nvarchar(50),@CurrentPostout nvarchar(50))RETURNS @table table(TotalNoSold INT,InitialMonth INT,InitialYear INT,EndingMonth INT,EndingYear INT,Postout nvarchar(50),HouseType nvarchar(50),AvgSellingPrice money)ASBEGINDECLARE @CurrentMonth intDECLARE @CurrentYear intDECLARE @TotalAverage moneySET @CurrentMonth = @InitialMonthSET @CurrentYear = @InitialYearWHILE (@NoSoldInMonth < 10)BEGIN;SET @CurrentMonth = @CurrentMonth+1IF @currentMonth=13 BEGIN SET @currentMonth = 1 SET @currentYear = @currentYear+1 ENDSELECT @NoSoldInMonth = COUNT(*), @TotalAverage = AVG(decPrice) FROM Postcode_Datesplit WHERE PostOut = @CurrentPostout AND((@InitialMonth <=MONTH(Application_Date) AND MONTH(Application_DATE) <= @CurrentMonth AND YEAR(Application_Date) = @InitialYear) OR (MONTH(Application_Date) <=@CurrentMonth AND @InitialYear < YEAR(Application_Date) AND YEAR(Application_Date) <= @CurrentYear))END;INSERT INTO @TABLE(TotalNoSold,InitialMonth,InitialYear,EndingMonth,EndingYear,Postout,HouseType,AvgSellingPrice)SELECT @NoSoldInMonth,@InitialMonth,@InitialYear,@CurrentMonth,@CurrentYear,@CurrentPostout,@CurrentHouseType,@TotalAverageRETURNEND The code I'm using to call the function is as follows:DELETE ExtendedPeriodsTableINSERT INTO ExtendedPeriodsTable([TotalNoSold],Postout,HouseType,[Begin_Period_Year],[Begin_Period_Month],[End_Period_Year],[End_Period_Month],Avg_Monthly_Price)SELECT query1.TotalNoSold,query1.Postout,query1.HouseType,query1.InitialYear,query1.InitialMonth,query1.EndingYear,query1.EndingMonth,query1.AvgSellingPrice FROM (select TOP 100 HouseData.Postout AS Unnecesary, s.*from HouseData cross apply dbo.ExtendedMonthsCreation(HouseData.NoOfHouses, HouseData.Month, HouseData.Year,HouseData.HouseType,HouseData.Postout) s WHERE NoOfHouses <10 AND PreviouslyUsedFlag IS NULL) AS query1 The format of the final data in the ExtendedPeriodsTable is:[TotalNoSold] ,[Postout] ,[HouseType] ,[Begin_Period_Year] ,[Begin_Period_Month] ,[End_Period_Year] ,[End_Period_Month] ,[Avg_Monthly_Price] FROM [MyHousePrice].[dbo].[ExtendedPeriodsTable] The problem is that I am getting rows in ExtendedPeriodsTable which begin on say January 2010 and end on March 2010 all within one group, but then the next group begins in February 2010 and ends on March 2010. I want to use some kind of flag to ensure that a month is only put in one group, and that the next group contains only months which have not previously been grouped, i.e April etc... As this is the first Function I've written I did so without realising I couldn't use an 'UPDATE' from within it, as I had originally intended. I've now discovered that the only way to use an update is to convert the function to a procedure, however I've tried that and that leaves me unable to call the procedure in the way I need. |
|
|
lappin
Posting Yak Master
182 Posts |
Posted - 2011-03-08 : 10:04:05
|
| You can start with a simple GROUP BY to get totals for each monthCREATE View y1 AS SELECT select month([DateColumn])as [MnthID] ,count(Sales) as Num FROM [dbo].[ATestTable] group by month([DateColumn])Then Join the View to itself by joining the month's Num to the next month's Num, and add the Num from the two months if it is <10Select y3.*,CASE when Num < 10 then (Num+(Select Num from (SELECT y1.[MnthID] ,count(Sales) as Num FROM y1 group by [MnthID]) y2 where y3.[MnthID]=y2.[MnthID]+1)) else Num end as combined from (SELECT y1.[MnthID] ,count(Sales) as Num, FROM y1 group by [MnthID] )as y3you could repeat this logic a few times using more subqueries and CASE statements. |
 |
|
|
lappin
Posting Yak Master
182 Posts |
Posted - 2011-03-08 : 10:06:05
|
| Sorry meant: Join the View to itself by joining the month's MonthID to the next month's MonthID |
 |
|
|
silver_surfer21
Starting Member
21 Posts |
Posted - 2011-03-08 : 10:43:20
|
Thanks, that looks like a simpler way of going about things than mine... I've tried it and it almost seems to work but then it comes up withMsg 512, Level 16, State 1, Line 2Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. Here's the code I'm usingDROP VIEW y1CREATE View y1 ASSELECT month as [MnthID],Year,Postout,HouseType,sum(NoOfHouses) as NumFROM [dbo].[HouseData]group by Postout,year,Month,HouseType/*Then Join the View to itself by joining the month's Num to the next month's Num, and add the Num from the two months if it is <10 */Select y3.*,CASE when Num < 10 then (Num+(Select Num from (SELECT y1.[MnthID],sum(num) as NumFROM y1group by Postout,Year,[MnthID],HouseType) y2 where y3.[MnthID]=y2.[MnthID]+1)) else Num end as combined from (SELECT y1.[MnthID],sum(num) as NumFROM y1group by Postout,Year,[MnthID],HouseType)as y3/*you could repeat this logic a few times using more subqueries and CASE statements. */ I suspect the problem is something to do with the fact that I've had to add a few more fields to the 'group by's' but I could be wrong |
 |
|
|
lappin
Posting Yak Master
182 Posts |
Posted - 2011-03-09 : 06:42:16
|
| I suspect the problem is in this line:group by Postout,Year,[MnthID],HouseType) y2 where y3.[MnthID]=y2.[MnthID]+1Possibly change to:group by Postout,Year,[MnthID],HouseType) y2 where y3.[MnthID]=y2.[MnthID]+1 and y3.HouseType=y2.HouseType and y3.Year=y2Yearthis is not going to work across years - i.e. Dec to JanProbably better to use "Month(DATEADD(month,-1,DateColumn))" to to join view to previous month's data. |
 |
|
|
|
|
|
|
|