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 |
|
johnnybutler7
Starting Member
16 Posts |
Posted - 2008-11-11 : 08:55:48
|
| Hi,I was wondering if anyone can help me,If i have 11 news items for March 2006id score1 12 23 34 45 56 67 78 89 910 1011 11What im trying to do is spike the data so i take 30% of the news items from the dataset follwoing these rules.So 30% of 11 is 3.3 so i want to round that down to 3 and in this case i want to take 2 news items from the top and then 1 news item from the bottom.If it was 4 i would tak 2 from the top and 2 from the bottom.SELECT TOP (round(count(news.id) / 30) * 100) / 2)) news.id, news.scoreFROM newsWHERE news.announced_date >= '2006-03-01' ANDnews.announced_date <= '2006-03-31'order by score DESCSo the calculation after the SELECT TOP would be (floor((11 * 30) / 100) / 2)) which would return 3expected results1 110 1011 11Can anyone help?JB |
|
|
sakets_2000
Master Smack Fu Yak Hacker
1472 Posts |
Posted - 2008-11-11 : 09:02:34
|
| You could put it in a variable , something like declare @n intset @n=3select top (@n) * from Table |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2008-11-11 : 09:09:32
|
[code]DECLARE @Sample TABLE ( ID INT, Score INT )INSERT @SampleSELECT 1, 1 UNION ALLSELECT 2, 2 UNION ALLSELECT 3, 3 UNION ALLSELECT 4, 4 UNION ALLSELECT 5, 5 UNION ALLSELECT 6, 6 UNION ALLSELECT 7, 7 UNION ALLSELECT 8, 8 UNION ALLSELECT 9, 9 UNION ALLSELECT 10, 10 UNION ALLSELECT 11, 11DECLARE @Part FLOAT, @Top INT, @Bottom INTSELECT @Part = 0.3, -- 30 percent @Top = FLOOR(@Part * COUNT(*))FROM @SampleSELECT @Bottom = @Top / 2, @Top = @Top - @BottomSELECT *FROM ( SELECT TOP (@Top) * FROM @Sample ORDER BY Score DESC ) AS dUNION ALLSELECT *FROM ( SELECT TOP (@Bottom) * FROM @Sample ORDER BY Score ) AS d[/code] E 12°55'05.63"N 56°04'39.26" |
 |
|
|
johnnybutler7
Starting Member
16 Posts |
Posted - 2008-11-11 : 10:22:23
|
| Thanks for the responses. Ive merged your example with my current query and come up with the below. The query is running but it returns every news item for that month(22) and the message print of the 2 variables @top and @bottom are,(22 row(s) affected)-----------------------Side = 430Perimeter = 429Ive tried various different combinations but always get 22 news items but that is the total for that month that have scores and not the subset im looking for.DECLARE @Part FLOAT, @Top INT, @Bottom INTSELECT @Part = 0.3, -- 30 percent @Top = FLOOR(@Part * COUNT(*))FROM newsSELECT @Bottom = @Top / 2, @Top = @Top - @BottomSELECT * FROM ( SELECT TOP (@Top) id FROM news WHERE news.announced_date >= '2006-03-01' AND news.announced_date <= '2006-03-31' AND news.score IS NOT NULL AND news.id IN (SELECT news.id FROM news INNER JOIN news_targets ON news_targets.news_id = news.id WHERE news_status_id <> 4) ORDER BY news.score ASC ) top_news UNION SELECT * FROM ( SELECT TOP (@Bottom) id FROM news WHERE news.id IN ( SELECT DISTINCT news.id FROM deals WHERE news.announced_date >= '2006-03-01' AND news.announced_date <= '2006-03-31' AND news.score IS NOT NULL AND news.id IN (SELECT news.id FROM news INNER JOIN news_targets ON news_targets.news_id = news.id WHERE news_status_id <> 4) ) ORDER BY news_score DESC ) bottom_newsPRINT '-----------------------';PRINT 'Side = ' + CONVERT(varchar(10), @Top, 10);PRINT 'Perimeter = ' + CONVERT(varchar(10), @Bottom, 10);Can you see anything wrong??JB |
 |
|
|
johnnybutler7
Starting Member
16 Posts |
Posted - 2008-11-11 : 10:46:33
|
| My mistake, i just relaised i needed to add the conditions to the initial sql queryDECLARE @Part FLOAT,@Top INT,@Bottom INTSELECT @Part = 0.3, -- 30 percent@Top = FLOOR(@Part * COUNT(*))FROM newsWHERE news.announced_date >= '2006-03-01' ANDnews.announced_date <= '2006-03-31' AND news.score IS NOT NULL AND news.id IN (SELECT news.id FROM newsINNER JOIN news_targets ON news_targets.deal_id = news.idWHERE news_status_id <> 4)SELECT @Bottom = @Top / 2,@Top = @Top - @BottomSELECT *FROM (SELECT TOP (@Top) idFROM newsWHERE news.announced_date >= '2006-03-01' ANDnews.announced_date <= '2006-03-31' AND news.score IS NOT NULL AND news.id IN (SELECT news.id FROM newsINNER JOIN news_targets ON news_targets.news_id = news.idWHERE news_status_id <> 4)ORDER BY news.score ASC) top_newsUNIONSELECT *FROM(SELECT TOP (@Bottom) idFROM newsWHERE news.id IN (SELECT DISTINCT news.idFROM dealsWHERE news.announced_date >= '2006-03-01' ANDnews.announced_date <= '2006-03-31' AND news.score IS NOT NULL AND news.id IN (SELECT news.id FROM newsINNER JOIN news_targets ON news_targets.news_id = news.idWHERE news_status_id <> 4))ORDER BY news_score DESC) bottom_newsPRINT '-----------------------';PRINT 'Side = ' + CONVERT(varchar(10), @Top, 10);PRINT 'Perimeter = ' + CONVERT(varchar(10), @Bottom, 10);This produces 6 record which im expecting 7 though 22 * 0.3 = 6.6 rounds to 7 so ive replaced Floor with roundthanks for your help guysJB |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2008-11-11 : 11:30:02
|
You can use CEILING as well. E 12°55'05.63"N 56°04'39.26" |
 |
|
|
|
|
|
|
|