0

这是我的问题:用户按尺寸搜索产品。结果应显示所需尺寸(如果有)的所有产品以及逐渐变大和变小的产品,直到除了尺寸正确的产品外,还显示至少 50 个尺寸过小的产品和 50 个超大尺寸的产品。

结果应始终显示一定尺寸的所有产品;换句话说,如果向上或向下移动到下一个尺寸会导致超过 50 种产品,请全部展示它们 - 不要停留在 50 种。

示例:假设有 25 个不同的尺寸,每个尺寸有 20 个产品。用户要求尺寸为 12。我们需要减小三个尺寸并增大三个尺寸才能在每个方向上至少获得 50 个尺寸。查询应返回所有尺寸为 12 的产品,以及尺寸为 9、10、11、13、14 和 15 的产品。该查询将返回总共 140 个产品(20 个尺寸 - 12 加上 60 和 60 以上)。不幸的是,尺寸不是像我的示例那样好的整数。它们是任意十进制值。

执行此操作的 Linq to SQL 查询非常酷,但也欢迎使用纯 SQL 或 C#。(我的环境是C#,SQL Server 2005)谢谢

4

2 回答 2

1

这是一个示例 SQL 语句(用于 mysql),它应该可以执行您想要的操作。但是根据您的程序正在执行的其他操作,您可能会发现在 C# 代码中执行某些处理会更快:

SELECT 
    *
FROM
    products
WHERE 
    size = [[desired_size]] OR 
    size IN (
         SELECT DISTINCT 
             size 
         FROM 
             products
         WHERE
             size > [[desired_size]]
         ORDER BY 
             size
         LIMIT 50
    )
    OR
    size IN (
         SELECT DISTINCT 
             size 
         FROM 
             products
         WHERE
             size < [[desired_size]]
         ORDER BY 
             size DESC
         LIMIT 50
    )

我将从头开始解释(并使用您的示例作为值)...

首先,我们需要生成接下来 50 个较大(或较小)项目的列表。以下查询应该这样做:

SELECT * FROM products WHERE size > 12 ORDER BY size LIMIT 50

所以,现在,我们正在从产品表中抓取所有大于所需尺寸的东西。我们按尺寸订购,然后将其限制为前 50 个。因此,在这种情况下,它应该返回(按此顺序)20 个尺寸为 13 的产品、20 个尺寸为 14 的产品和 10 个尺寸为 15 的产品。您可以尝试这在 Visual Studio SQL 编辑器中,并查看它返回的行。

但是出于我们的目的,我们只需要一个大小列表,因此我们可以通过将 SELECT 子句更改为:

SELECT DISTINCT size...

所以,现在我们只看“大小”列,我们使用 DISTINCT 关键字来避免重复值

所以现在,查询只返回列表: (13, 14, 15)

我们进行类似的查询以获取接下来的 50 个较小的项目:

SELECT DISTINCT size FROM products WHERE size < 12 ORDER BY size DESC LIMIT 50

这与上面的查询相同,但我们只限制了较小的尺寸,并且我们颠倒了顺序,所以我们得到了小于所需尺寸的 50 个最大的项目。

在这种情况下,此查询将返回列表 (11, 10, 9)

如果我们使用这两个列表将它们放在外部查询中,我们会得到:

SELECT
  *
FROM
  products
WHERE
  size = 12 OR
  size IN (13, 14, 15) OR
  size IN (11, 10, 9)

所以我们拉所有尺寸为9到15的产品

我希望这是有道理的 :-)

于 2009-11-15T20:33:11.627 回答
0

有点晚了,所以你可能已经解决了这个问题......

您遇到的问题似乎是您无法轻松定义结果集的边界条件。

您显然可以轻松做到:

Get me everything of size X
Get me 50 of size >X
Get me 50 of size <X

但是,由于大小是线性的而不是离散的,并且我们无法预测每种大小存在多少,我们无法对大小进行分组/计数,这使得很难确定哪个大小在 +/-50 条记录之外 -因此,我们需要在获得最终记录集之前读取这些值。可以其与子查询合并为一个,但如果 LINQ 在多个请求中执行,我不会感到惊讶,,,,

就像是:

Dim ExactSize = 1.1

Dim MaxSizeRecord = MyRepository.Get(function(x) x.Size > ExactSize).OrderBy(function(y) y.Size).Skip(50).First
Dim MinSizeRecord = MyRepository.Get(function(x) x.Size < ExactSize).OrderByDescending(function(y) y.Size).Skip(50).First

Dim FinalResults = MyRepository.Get(function(x) x.Size >= MinSizeRecord.Size and X.Size <= MaxSizeRecord.Size)

我还没有充分利用 LINQ 的胆量来知道是否......

Dim MaxSize = MyRepository.Get(function(x) x.Size > ExactSize).OrderBy(function(y) y.Size).Skip(50).First.Size
Dim MinSize = MyRepository.Get(function(x) x.Size < ExactSize).OrderByDescending(function(y) y.Size).Skip(50).First.Size

Dim FinalResults = MyRepository.Get(function(x) x.Size >= MinSize and X.Size <= MaxSize)

(即获取边界的确切大小,而不是大小恰好在边界处的记录)

...会生成相同的 SQL - 它当然更具可读性,但 LINQ 可能会立即执行 Min/Max 查询,因为值存储在 Double 中 - 通过隐式定义 MinSize/MaxSize 的类型,它可能会处理它作为一个 IQueryable(双)。

使用记录而不是双精度,同时可读性稍差,应该保证它被视为查询而不是值。

于 2010-08-12T17:18:19.417 回答