2013-04-19 3 views
0

У меня есть 2 таблицы базы данныхВыбор различных значений из пар ключ/значение в отдельной таблице

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

где JOB_PARAMETERS существу карта, содержащая параметр задания пары значение ключа. Каждое задание может иметь уникальные пары параметров/значений параметров.

Я ищу, чтобы прагматично построить запрос, который будет возвращать разные идентификаторы задания, содержащие комбинации клавиш/значений. Где значения фактически представляют собой список значений, операторов сравнения. Например:

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

Приведенный выше пример будет автоматически отфильтровывать все задания, которые не имеют ключа Файл_вывода и ПРИОРИТЕТ. Возврат всех заданий, соответствующих обеим условиям.

Я также должен иметь возможность поддерживать разбивку на страницы и порядок.

Я планировал использовать Perl с DBIx :: Class, но я могу сделать это и в чистом Perl/SQL.

Я открыт для изменения схемы базы данных, но каждое задание может иметь разные пары ключ/значение, поэтому я не могу просто сделать их столбцами в таблице заданий.

Заранее спасибо.

+0

являются имена параметров уникальны для данной работы? – a1ex07

+0

Да, они должны быть уникальными – Smartelf

ответ

1

При использовании DBIx :: Class вы можете сгенерировать схему DBIC с помощью Schema :: Loader.

После подключения к базе данных вы получите объект схемы $ вы можете использовать, чтобы получить ResultSet фильтруется, чтобы вернуть результат объекты вы хотите:

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; 
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).

+0

Спасибо, обратите внимание, конечно, почему вы положили предложение HAVING COUNT(). У заданного задания может быть больше пар ключ/значение, которые просто игнорируются или могут использоваться для order_by. – Smartelf

+0

@Smartelf: Без предложения 'HAVING' будут возвращены все группы, которые соответствуют предложению' WHERE' (т. Е. Соответствуют по меньшей мере одному параметру); условие 'HAVING' гарантирует, что возвращаются только те группы, которые содержат два совпадения записи (т. е. соответствие по обоим параметрам). – eggyal