【问题标题】:ORDER BY multi-valued field in an Access queryAccess 查询中的 ORDER BY 多值字段
【发布时间】:2015-03-01 20:50:23
【问题描述】:

关于我为什么使用多值字段的介绍,如果您愿意,可以跳过:我知道多值字段被认为是有害的,但我对它有很好的用途。我的物品有些属于 A 类,有些属于 B 类,有些属于两者。类别 A 和类别 B 不在数据库中的任何地方使用,除了在这个表中,并且与数据库的其余部分无关,而且 Access 漂亮的复选框/组合框非常适合选择适当的类别,比任何其他界面都好我将能够使用多对多表关系,或者仅使用两个单独的字段类别 A 和类别 B(特别是因为这两个类别中都有项目的情况非常罕见)。

话虽如此,我无法获得我想要的结果。我有一个表单,我希望用户能够在组合框中选择项目,并且我希望它首先显示 A 类中的所有项目(无论它们是否也在 B 类中),然后才显示显示所有不在类别 A 中的项目,因为类别 A 项目更有可能被用户选择,所以我希望它们更易于访问。

我无法管理这个。我尝试了 ORDER BY、SELECT DISTINCT 等各种选项,但我无法找出任何适用于多值字段的方法。然后我尝试执行一个选择所有 A 类项目的查询,然后是另一个选择所有非 A 类项目的查询。这些查询中的每一个都可以单独工作,但 Access 不允许我将它们联合在一起。

【问题讨论】:

  • 欢迎使用关系格式的多值字段。如果我们看到一些疑问,我们将能够提供帮助,但您的问题不会得到答案。向我们展示一些查询,也许还有一个示例行。

标签: sql ms-access union multivalue


【解决方案1】:

请记住,大多数多值数据库系统都能够执行所谓的爆炸式选择或排序。原来 Access 也有这个能力。

假设以下查询:

SELECT ID, FirstName, Color FROM customers
WHERE ID = 4

注意上面在查询生成器中的样子:

请注意以上如何扩展 mv 列的颜色。

上述查询的结果如下:

注意结果如何是 ONE RECORD(一行)和 Colors 的多值字段(它们是用户最喜欢的颜色)。

注意在查询生成器中关闭您会看到该列,但请注意如何将子列选择为“值”(.value)。

因此我们现在在查询构建器中选择这个:

生成的 sql 如下所示:

SELECT ID, FirstName, Color.Value FROM customers
WHERE ID =4

结果是这样的:

注意 ONE 行如何变成 3 行。这实际上就像子表的左连接。这意味着我们可以在此列上进行排序。

因此,只需构建一个查询,您将在其中放入 .value 列,然后您可以按照您的要求在您的报告中对这些数据进行排序和分组。

所有 A 类项目都应首先显示,然后将显示任何包含其他内容的记录。所以包括 .value 会爆炸,或者“扩展”结果查询,就好像它是一个单独的表一样。因此,您可以根据此结果对报告进行排序。

【讨论】:

  • 其实我已经试过了,问题是如果某样东西同时出现在Category 1和Category 2中,那么它会出现不止一次。我尝试只选择唯一值,但当涉及多值字段时,Access 不允许这样做。
  • 查看 Gord Thompson 新编辑的答案,该答案与您的答案相似,但增加了处理我提到的问题的转折。
【解决方案2】:

考虑一个名为 [Supplier] 的表,其中包含示例数据

ID  CompanyName  Categories
--  -----------  ----------------------
 1  Company 1    Category A
 2  Company 2    Category B
 3  Company 3    Category A, Category B
 4  Company 4    Category B
 5  Company 5    Category A, Category B

查询

SELECT 
    ID, 
    CompanyName,
    Categories,
    DCount("*", "Supplier", "ID=" & ID & " AND Categories.Value='Category A'") AS CountCatA
FROM
    Supplier

会回来

ID  CompanyName  Categories              CountCatA
--  -----------  ----------------------  ---------
 1  Company 1    Category A                      1
 2  Company 2    Category B                      0
 3  Company 3    Category A, Category B          1
 4  Company 4    Category B                      0
 5  Company 5    Category A, Category B          1

因此,我们将在 ORDER BY 子句中使用它,而不是使用 DCount() 填充列

SELECT 
    ID, 
    CompanyName,
    Categories
FROM
    Supplier
ORDER BY
    DCount("*", "Supplier", "ID=" & ID & " AND Categories.Value='Category A'") DESC,
    ID

返回

ID  CompanyName  Categories
--  -----------  ----------------------
 1  Company 1    Category A
 3  Company 3    Category A, Category B
 5  Company 5    Category A, Category B
 2  Company 2    Category B
 4  Company 4    Category B

编辑回复:cmets

如果您怀疑DCount() 函数可能会减慢速度,那么您可以尝试使用SUM()GROUP BY 的替代方法:

SELECT 
    ID, 
    First(CompanyName_) AS CompanyName, 
    First(Categories_) AS Categories
FROM
    (
        SELECT
            ID,
            CompanyName AS CompanyName_,
            Categories AS Categories_,
            IIf(Categories.Value='Category A',1,0) AS IsPreferredCategory
        FROM Supplier
    )
GROUP BY ID
ORDER BY
    SUM(IsPreferredCategory) DESC,
    ID

【讨论】:

  • 这行得通,所以我把它标记为答案,但我确实有一点抱怨——它很慢。对于我的大约 100 条记录的小表,计算查询需要几秒钟。这不是世界末日,因为我不希望有超过 200 条记录,但如果有更快的解决方案就好了。
  • 当然,最好的方法是如果我们能找到使用 count 代替 dcount 的方法。
  • 太棒了!它完美地运行并立即运行。我花了一段时间才弄明白你的代码并弄明白它的为什么它的工作原理......这与 Albert D. Kallal 的答案相差不远,但有一个额外的转折。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-14
  • 2019-01-21
  • 1970-01-01
  • 2012-12-31
  • 1970-01-01
相关资源
最近更新 更多