2010-08-07 3 views
2

Определение проблемы.Как это сделать, и order_by на DBIx :: Class :: ResultSet

У меня есть несколько клиентов с несколькими пользователями. Каждый клиент должен иметь возможность связывать пользовательские данные с пользователем, искать и заказывать.


База данных решений:

Таблица Customfields которая определяет таблицу customfields. Он имеет идентификатор и имя. Имеет отношение has_many с таблицей Userfields (иначе называемые атрибутами).

Таблица Userfields имеет идентификатор пользователя, customfieldid, контент и идентификатор. Это BELONGS_TO таблицу UserAccounts (так называемый «UserAccount») и Customfields (так называемый «customfield»)


Предлагаемое отборное заявление, что я хочу:

Это оператор выбора, который достигает и производит то, что Мне нужно.

SELECT ua.*, (
    SELECT content FROM Userfields uf 
    INNER JOIN Customfields cf 
     ON cf.id = uf.customfieldid 
    WHERE cf.name = 'Mothers birthdate' 
    AND uf.uid=ua.uid 
) AS 'Mothers birthdate', 
    (
    SELECT content FROM Userfields uf 
    INNER JOIN Customfields cf 
     ON cf.id = uf.customfieldid 
    WHERE cf.name = 'Join Date' AND 
    uf.uid=ua.uid 
) AS 'Join Date' 
FROM UserAccounts ua 
ORDER BY 'Mothers birthdate'; 

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


Вопрос

Как я могу добиться этого с -> Поиск по моему DBIx класса результирующего или как я могу добиться того же результата с поиском на моем DBIx класса результирующего?

Вот как я обычно выбираю из таблицы Useraccounts, хотя я не уверен, как выполнить сложное заявление, которое я хочу отсюда.

my @users = $db->resultset('Useraccounts')->search(
    undef, 
    { 
     page  => $page, 
     join  => 'attributes', 
     ... 
    }); 

Спасибо за ваше время.

-pdh

+0

Я слишком устал, чтобы попытаться ответить на это, но человек, я должен дать вам реквизит для составления такого хорошо написанного вопроса! –

+0

Cheers JGB; надеюсь, это послужит хорошим ответом :) –

ответ

2

Это действительно очень волосатый, и любое решение не будет красиво, но это делает взгляд возможным, если согнуть правила немного. Простите любые ошибки, которые я делаю, поскольку я не пошел и не создал схему, чтобы проверить это, но она основана на лучшей информации, которую я имею (и много помощи от рибасуши).

Во-первых, (при условии, что ваша таблица userfields имеет belongs_to отношение с таблицей customfields, называется customfield)

my $mbd = $userfields_rs->search(
    { 
     'customfield.name' => 'Mothers birthdate', 
     'uf.uid' => \'me.uid' # reference to outer query 
    }, 
    { 
     join => 'customfield', 
     alias => 'uf', # don't shadow the 'me' alias here. 
    } 
)->get_column('content')->as_query; 

# Subqueries and -as don't currently mix, so hack the SQL ourselves 
$mbd->[0] .= q{ AS 'Mothers Birthdate'}; 

Буквальный me.uid что uf.uid в настоящее время сопоставляется является несвязанной переменной - это uid из запроса, который мы в конечном итоге собираем включить в этот подзадач. По умолчанию DBIC псевдонизирует таблицу, в которой запрос обращается к me; если вы дали ему другой псевдоним, тогда вы бы использовали что-то другое. В любом случае, вы могли бы повторить этот бизнесстолько раз, сколько хотите, просто изменив имя поля (если вы умны, вы напишите метод их генерации) и поместите их в массив, поэтому теперь предположим, что @field_queries - это массив, содержащий $mbd выше, а также еще один на основе даты регистрации и всего, что вам нравится.

Как только вы что, это как «простой», как ...

my $users = $useraccounts_rs->search(
    { }, # any search criteria can go in here, 
    { 
     '+select' => [ @field_queries ], 
     '+as' => [qw/mothers_birthdate join_date/], # this is not SQL AS 
     order_by => {asc => 'Mothers birthdate'}, 
    } 
); 

, который будет включать в себя каждый из подзапросов в выбор.

Теперь для печальной части: на данный момент все это на самом деле не будет работать, потому что подзапросы с заполнителями не работают должным образом. Итак, для этого вам понадобится дополнительное обходное решение: вместо 'customfield.name' => 'Mothers birthdate' в подзапросе поиска, do 'customfield.name' => \q{'Mothers birthdate'} - это использует литерал SQL для имени поля (BE CAREFUL SQL-инъекции здесь!), Который обойдется ошибкой заполнителя. Но в недалеком будущем эта ошибка будет решена, и код выше будет работать нормально, и мы обновим ответ, чтобы вы знали, что это так.

+0

Большое спасибо Хоббс (и Рибасуси) :). Это больше помогает, чем я мог надеяться в течение такого короткого промежутка времени: D. Много удовольствия для вас :) –

+0

Два пункта к этому. 1) -> get_column ('content') -> as_query; возвращает ссылку на ссылку массива, а не ожидаемую ссылку на массив, это может быть ошибкой в ​​моем текущем классе dbix ::, но я не видел никаких исправлений, упомянутых в файле изменений, и, как представляется, документация предполагает, что это ожидаемое поведение! Я решил это, выполнив $ {$ userfields_rs-> search (...)} 2) Я решил проблему с заполнителем, добавив 'bind' => $ mbd -> [1] в мой -> поиск. После долгих игр этим утром все работает :) –

+0

Небольшая проблема, если я звоню -> пейджинг на наборе результатов, я не могу получить -> total_entries из него, похоже, что он захватывает заполнители, которые ему не нужны, добавляет их до конца, что вызывает ошибку. теперь обойти это с помощью eval, но это уродливо. –