我的问题是:
SQL Server数据库表
AdId AdName AdUrl Credits
1 Ad1 abc.com 10
2 Ad2 def.com 40
3 Ad3 fgi.com 30
4 Ad4 xyz.com 10
以上广告表可能包含的记录1000的。我想一次显示10个广告(通过向具有较高价值学分的重要性)。
我的方法
LINQ
var result = (from u in idb.ads
select u).OrderBy(x => Guid.NewGuid()).Take(10);
但是,这不会采取更高的学分来考虑。
它是正确的做法?如何显示随机广告(含考虑到学分)和相同的广告不会显示地重复?
尝试以下操作:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication100
{
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("AdId", typeof(int));
dt.Columns.Add("AdName", typeof(string));
dt.Columns.Add("AdUrl", typeof(string));
dt.Columns.Add("Credits", typeof (int));
dt.Rows.Add(new object[] {1, "Ad1", "abc.com", 10});
dt.Rows.Add(new object[] {2, "Ad2", "def.com", 40});
dt.Rows.Add(new object[] {3, "Ad3", "fgi.com", 30});
dt.Rows.Add(new object[] {4, "Ad4", "xyz.com", 40});
Random rand = new Random();
List<DataRow> randomRows = dt.AsEnumerable().Select(x => new { row = x, rand = rand.Next() }).OrderBy(x => x.rand).Select(x => x.row).ToList();
DataTable dt2 = randomRows.CopyToDataTable();
}
}
}
如何显示随机广告(含考虑到学分)和相同的广告不会显示地重复?
如果您想对信贷为主,可以尝试编写查询类似下面(您可能需要将其转换为LINQ)。
这里有记录更多的信贷将获得更多的优先权。像credit > 80
将获得最高优先级,credit < 40
将得到最低优先级。
SELECT TOP 10 *
FROM (SELECT *
FROM (SELECT TOP 80 *
FROM [table]
WHERE credit > 80
ORDER BY Newid())A
UNION ALL
SELECT *
FROM (SELECT TOP 60 *
FROM [table]
WHERE credit <= 80
AND credit > 60
ORDER BY Newid())B
UNION ALL
SELECT *
FROM (SELECT TOP 40 *
FROM [table]
WHERE credit <= 60
AND credit > 40
ORDER BY Newid())C
UNION ALL
SELECT *
FROM (SELECT TOP 20 *
FROM [table]
WHERE credit <= 40
ORDER BY Newid())D) T
ORDER BY Newid()
你写了:
通过向具有较高价值的重要性学分
这是否意味着,只要你不显示信贷40的广告,你不希望显示信贷10在所有的广告吗?或者,你的意思是你想给具有较高信用的广告更高的机会被显示。如果是的话:如果信用是4时高,应该要显示的机会,有四个时间做大?
让我们假设你不想要,只要你有更高的学分不显示的广告,以显示与低信用的广告。
int nrOfAdsToSelect = ...;
var selectedAds = dbContext.Adds
.Where(ad => !ad.IsSelected)
.OrderyDescending(ad => ad.Credit)
.Take(nrOfAddsToSelect);
但是,如果你想为所有的广告有机会显示,具有较高的信用只有广告的机会较高,你应该想想如何可能性要高得多。
最简单的是将信贷转化为整数范围,说明时,应选择广告:
Id Credit => Range
00 01 00
01 01 01
02 02 02, 03 // credit 2: 2 numbers
03 03 04, 05, 06 // credit 3: 3 numbers
04 10 07, 08, 09, 10, 11, 12, 13, 14, 15, 16 // 10 numbers
采取随机数在范围[00,16]。这个Id 04选择的机会是比编号01被选择的几率高10倍。
所以,你需要一个函数从信贷和StartNumber创建一个整数范围。这可以简单如上述,它可以是任何其他的算法,这取决于你有多少具有较高信用评级的广告的机会。
您可以使用您的信用卡对范围功能不显示增加了一个序列转换成整数的序列。
作为扩展功能:
static IEnumerable<int> ToRange(this int credit, int startNumber)
{
// example: Credit 40 is 40 times more chance than credit 1.
// so range length is equal to credit
return Enumerable.Range(startNumber, credit);
}
static IEnumerable<int> ToRange(this IEnumerable<Ad> adds)
{
int startNumber = 0;
foreach (Ad add in adds)
{
// only use ads that are not displayed yet to select a new Ad.
if (!ad.IsDisplayed)
{
var range = add.Credit.ToRange();
foreach (var value in range) yield return value;
}
}
}
用法:
List<Ad> ads = ...
var range = ads.ToRange().ToList();
int selectedIndex = rnd.Next(range.Count);
var firstSelectedAdd = ads[selectedIndex];
问题是,一旦你选择了你的第一个广告,你的第二广告的机会应该改变。你需要创建一个新的范围:
static Ad Select(this IReadOnlyList<Ad> ads)
{
var range = ads.ToRange().ToList();
int selectedIndex = rnd.Next(range.Count);
return ads[selectedIndex];
}
static IEnumerable<Ad> SelectAds(this IEnumerable<Ad> ads, int selectCount)
{
for (int i=0; i<selectCount; ++i)
{
var selectedAd = ads.Select();
yield return selectedAd;
selectedAd.IsDisplayed = true; // to make sure it is not selected again
}
}