2

問題定義。

複数のユーザーを持つ複数のクライアントがあります。各クライアントは、カスタム データをユーザー、検索、および順序付けに関連付けることができる必要があります。


データベース ソリューション:

customfields テーブルを定義するテーブル Customfields。IDと名前があります。これには、Userfields テーブル (別名「属性」) との has_many 関係があります。

Userfields テーブルには、userid、customfieldid、content、および id があります。これは、Useraccounts テーブル (別名「useraccount」) および Customfields (別名「customfield」) に属しています。


私が望む提案されたselectステートメント:

これは、必要なものを達成して生成する select ステートメントです。

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';

この場合、それらは select ステートメント内の 0 ... x サブ select ステートメントのいずれかであり、それらのいずれかまたはいずれも順序付けする必要がない可能性があります。


質問

dbix クラスの結果セットで ->search を使用してこれを達成するにはどうすればよいですか? または、dbix クラスの結果セットで検索を使用して同じ結果を得るにはどうすればよいですか?

Useraccounts テーブルから通常選択する方法は次のとおりですが、ここから必要な複雑なステートメントを実行する方法がわかりません。

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

御時間ありがとうございます。

-pdh

4

1 に答える 1

3

これは非常に難しい問題であり、どのような解決策もうまくいくとは限りませんが、ルールを少し曲げれば、解決できるように見えます。これをテストするためのスキーマを作成したわけではありませんが、これは私が持っている最良の情報 (および ribashi からの多くの助け) に基づいています。

まず、(userfields テーブルに、customfields テーブルとの belongs_to 関係があると仮定します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.uiduf.uid が照合されるリテラルはバインドされていない変数uidです。これは、最終的にこのクエリを副選択として入れるクエリのフィールドです。デフォルトでは、DBIC はクエリがアドレス指定するテーブルにエイリアスを設定しますme。別のエイリアスを指定した場合は、ここで別のものを使用します。とにかく、フィールド名を変更するだけで、好きなだけ多くの異なるフィールドでこのas_queryビジネスを繰り返すことができ(賢い場合は、それらを生成するメソッドを作成します)、それらを配列に入れます。上記の配列と、参加日に基づく別の配列、および好きなものを@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'副選択検索の代わりに'customfield.name' => \q{'Mothers birthdate'}、フィールド名にリテラル SQL を使用しています (ここでは SQL インジェクションに注意してください!)。これにより、プレースホルダーのバグが回避されます。しかし、それほど遠くない将来に、そのバグは解決され、上記のコードは問題なく動作するようになります。それが事実であることをお知らせするために回答を更新します。

DBIx::Class::ResultSource order_by ドキュメントを参照してください

于 2010-08-07T09:44:55.203 に答える