【问题标题】:Selecting distinct values from key/value pairs in a seperate table从单独的表中的键/值对中选择不同的值
【发布时间】:2013-04-12 23:54:48
【问题描述】:

我有 2 个数据库表

JOBS(JOB_ID, JOB_TIME, JOB_NAME,...), JOB_PARAMETERS(JOB_ID,NAME,VALUE)

其中 JOB_PARAMETERS 本质上是一个包含作业参数键值对的映射。 每个作业都可能有一个唯一的参数键/值对。

我希望以务实的方式构建一个查询,该查询将返回包含键/值组合的不同作业 ID。这些值实际上是一个值列表,比较运算符。 例如:

JOB_PARAMETERS: NAME = 'OUTPUT_FILENAME', VALUE LIKE "ALEX%", "JAX%"
                NAME = 'PRIORITY' , VALUE > 7

上面的示例会自动过滤掉所有没有 OUTPUT_FILENAME 和 PRIORITY 键的作业。返回同时满足这两个条件的所有工作。

我还需要能够支持分页和排序。

我计划将 Perl 与 DBIx::Class 一起使用,但我也可以在纯 Perl/SQL 中完成。

我愿意更改数据库架构,但每个作业都可以有不同的键/值对,所以我不能只在作业表中将它们设为列。

提前致谢。

【问题讨论】:

  • 给定作业的参数名称是否唯一?
  • 是的,它们应该是唯一的

标签: mysql perl dbi dbix-class


【解决方案1】:

可以在 SQL 中通过 JOB_PARAMETERS 分组 JOB_ID 并相应地过滤组来实现。例如,如果(JOB_ID, NAME)存在唯一性约束,可以查询如下:

SELECT   JOB_ID
FROM     JOB_PARAMETERS
WHERE    (NAME='OUTPUT_FILENAME' AND (VALUE LIKE 'ALEX%' OR VALUE LIKE 'JAX%'))
      OR (NAME='PRIORITY' AND VALUE > 7)
GROUP BY JOB_ID
HAVING   COUNT(*) = 2

如果没有这样的唯一性约束,COUNT(*) 将不得不被替换,例如COUNT(DISTINCT NAME)

【讨论】:

  • 谢谢,请注意为什么要放置 HAVING COUNT() 子句。给定的作业可能有更多的键/值对被忽略,或者可以用于 order_by。
  • @Smartelf:如果没有HAVING 子句,将返回所有匹配WHERE 子句的组(即至少匹配一个参数); HAVING 子句确保只返回那些包含两个记录匹配(即两个参数都匹配)的组。
【解决方案2】:

使用 DBIx::Class 时,您可以使用 Schema::Loader 生成 DBIC 模式。

连接到数据库后,您会得到一个 $schema 对象,您可以使用它来获取过滤后的 ResultSet 以返回您想要的 Result 对象:

my $rs_job_parameters = $schema->resultset('Job_Parameters')->search({
    -or => [
        {
            'name' => 'OUTPUT_FILENAME',
            'value' => [{ like => 'ALEX%'}, { like => 'JAX%' }].
        },
        {
            'name' => 'PRIORITY',
            'value' => [{ '>' => 7}].
        }
    ]},
    {
        columns  => [qw( job_id )],
        group_by => [qw( job_id )], # alternative you can use distinct => 1 to group_by all selected columns
        having   => \[ 'COUNT(*) = ?', [ 2 ] ],
    }
);

my @job_ids = $rs_job_parameters->get_column('job_id')->all;

【讨论】:

    猜你喜欢
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-06
    • 2012-07-15
    • 2011-01-28
    • 1970-01-01
    • 2020-03-27
    相关资源
    最近更新 更多