1

我有大量数据需要根据搜索查询以特定方式排序,但我不确定最佳方法。

我要排序的数据是按学校分组的课程列表。每门课程由一所学校教授。每个学校可能属于任意数量的“伙伴关系”,这代表了许多学校之间的关系。用户可以通过课程名称搜索任意数量的课程。

我需要对数据进行如下排序:

  • 课程按学校分组,每页显示 10 所学校。

  • 可以提供用户搜索过的每门课程的学校应该首先出现在列表中。

  • 在这些结果之后,属于可以容纳用户搜索的所有课程的合作伙伴的学校应该彼此相邻出现。

这是一个例子:

  • A教授历史、法语和英语课程。
  • B教法语和数学。
  • C教授历史。
  • BC是合伙人。
  • D教历史。

  • 用户搜索“历史”和“法语”。

  • A应该首先出现在结果中,它的历史和法语课程,因为它可以提供用户正在寻找的两个课程。

  • 接下来出现B,紧接着是C,其所教授的相关课程列在其后,因为合作伙伴可以提供用户所需的两门课程。

  • D接下来出现,因为它只提供 1 门相关课程。

数据跨几个表存储在 Microsoft SQL Server 数据库中。这是一个简化的架构:

课程:

  • 内部编号
  • varchar 名称
  • 诠释学校ID

学校:

  • 内部编号
  • varchar 名称

合伙:

  • 内部编号
  • varchar 合伙人名称

学校合作:

  • 内部编号
  • 诠释学校ID
  • 内部伙伴关系 ID

有超过100000门课程和大约300所学校。我不知道如何按照 SQL 中指定的方式对课程进行排序,我认为这是我最大的问题。我只需要在每页显示 10 个结果,但由于无法在 SQL 查询中进行排序,我必须提取整个结果集并在 PHP 中手动对其进行排序,然后才能将结果集减少到 10 个结果。

我目前正在使用 Doctrine 2 在具有多个连接的单个查询中提取我需要的数据,将结果水合为一个数组。然后计划是在 PHP 中操作这个大的记录数组以使其进入正确的顺序。由于这个数组的大小,我担心这个排序过程会很慢,所以我正在寻找有关如何更快地进行排序的建议,方法是:

  • 处理 SQL 查询中的排序。
  • 建议如何在 Solr 等搜索引擎中实现上述算法(我对这方面的基础知识有一点经验,但不会执行复杂的排序)。
  • 如果其他两个选项不可行,关于如何最好地在 PHP 中执行排序的建议。

编辑:

我在这方面取得了一些不错的进展,谢谢(尤其是@Neil)。我已经打开了一个单独的问题(子查询上的 Groupwise MAX()),其中包含我到目前为止的一些进展。

4

3 回答 3

0

按匹配课程的数量查找学校很简单:

SELECT schoolId, COUNT(*) AS schoolCount
  FROM Courses
  WHERE name IN ('History', 'French')
  GROUP BY schoolId

如果这就是你所需要的,你可以ORDER BY schoolCount DESC按照你想要的顺序得到它们。

要找到与匹配课程的合作伙伴,您首先需要找到在至少一所学校开设课程的合作伙伴:

SELECT partnershipId, COUNT(DISTINCT name) AS partnershipCount
  FROM SchoolPartnership
  INNER JOIN Courses ON Course.schoolId = SchoolPartnership.schoolId
  WHERE name IN ('History', 'French')
  GROUP BY partnershipId

请注意,这DISTINCT是必需的,因为我们不在乎合作伙伴中有多少学校有该课程。如果你没有,DISTINCT那么你可以使用一个子选择来代替:

SELECT partnershipId, COUNT(*) AS partnershipCount
  FROM (
    SELECT DISTINCT partnershipId, name
      FROM SchoolPartnership
      INNER JOIN Courses ON Course.schoolId = SchoolPartnership.schoolId
      WHERE name IN ('History', 'French'))
  GROUP BY partnershipId

然后,您可以将上面的第一个和最后一个查询用作与 SchoolPartnership 的连接中的子选择,以按 partnerMatches 和 schoolMatches 的降序排列学校。(请注意,我假设所有学校都与至少一所学校合作。)我认为最终查询将如下所示:

SELECT SchoolMatches.schoolID
  FROM (
    SELECT schoolId, COUNT(*) AS schoolCount
      FROM Courses
      WHERE name IN ('History', 'French')
      GROUP BY schoolId
  ) SchoolMatches
  JOIN SchoolPartnership ON SchoolMatches.schoolID = SchoolPartnership.schoolID
  JOIN (
    SELECT partnershipId, COUNT(DISTINCT name) AS partnershipCount
      FROM SchoolPartnership
      INNER JOIN Courses ON Course.schoolId = SchoolPartnership.schoolId
      WHERE name IN ('History', 'French')
      GROUP BY partnershipId
   ) PartnershipMatches ON SchoolPartnership.schoolId = PartnershipMatches.schoolId
   ORDER BY PartnershipMatches.partnershipCount DESC, SchoolMatches.SchoolCount DESC
于 2013-02-09T20:56:49.767 回答
0

我们对网站的页面也有类似的问题。我们创建了具有所有参数的特殊去规范化搜索表,以执行没有子查询或连接的搜索。所有数据都是重复的,所以当发生变化时,我们会更新所有非规范化数据。我们使用后台任务来同步数据,因此搜索结果在短时间内可能不是实际的。

可能看起来很复杂,但这只有在您的数据和请求会增长的情况下才会如此。

于 2013-02-10T14:14:25.823 回答
-2
filter_var('sgamgee@example.com', FILTER_VALIDATE_EMAIL); // Returns "sgamgee@example.com"

这是一个有效的电子邮件地址。

于 2013-12-17T11:59:12.793 回答