1

このSQLFiddleを参照してください:http ://sqlfiddle.com/#!2/9db4f

表「rate」は、ジョブロールの時間単位のチャージアウトレートを格納し、クライアントの会社、グループ(「グループ」は会社の​​単なる部門)、およびクライアントの連絡先に基づいてロールのさまざまなレートを格納するオプションがあります。

料金も時間とともに変化する可能性があります。

役割、会社、グループ、連絡先の特定の組み合わせに対して、最新の最適なレートを1つ選択したいと思います。次の順序で一致を試みる必要があります。

  1. client_contact、client_group、client_companyおよびrole
  2. client_group、client_companyおよびrole
  3. client_companyと役割
  4. ただの役割

例:レートマッチングの役割ID 3、会社ID 3、クライアントID4を探しています。

これらすべてに一致するレコードはないため、ロールID3と会社ID3だけに一致するレコードを探す必要があります(他のフィールド(client_contactとclient_group)はNULLである必要があります)。それらの2つがあります:行IDの2と3。最新の「date_from」日付を持っているので、行ID3を選択する必要があります。

別の例:役割ID3と会社ID25に一致するレートを探しています。どちらも存在しないため、役割ID 3だけに一致するものを探し、他のすべての値にはNULLを探す必要があります。一致する行は1つだけです:番号1。

現在のSQLFiddleのクエリは、'最新の'ビットをフェッチしますが、オプションの列が存在する場合は、それを一致させることに固執しています。

ハルプ:(

編集:おっと、SQLFiddleはスキーマのみを保存し、クエリは保存しないようです。これは私が持っているものです:

SELECT 
  rate.*
FROM
  rate
LEFT JOIN rate AS newest ON (
  rate.role = newest.role
  AND COALESCE(rate.client_company, 1) = COALESCE(newest.client_company, 1)
  AND COALESCE(rate.client_group, 1) = COALESCE(newest.client_group, 1)
  AND COALESCE(rate.client_contact, 1) = COALESCE(newest.client_contact, 1)
  AND newest.date_from > rate.date_from
)
WHERE newest.id IS NULL
4

3 に答える 3

2

このようにアプローチします。

あなたが探していると仮定して:

client_contact = 5
client_group= 3
client_company= 3
role = 3  

クエリ:

select *
from rate
where ifnull(client_contact, 5) = 5
    and ifnull(client_group, 3) = 3 
    and ifnull(client_company, 3) = 3 
    and ifnull(role, 3) = 3
order by case
    when client_contact = 5 and client_group = 3 and client_company = 3 and role = 3
      then 1
    when client_contact is null and client_group = 3 and client_company = 3 and role = 3
      then 2
    when client_contact is null and client_group is null and client_company = 3 and role = 3
      then 3
    when client_contact is null and client_group is null and client_company is null and role = 3
      then 4
end, date_from desc
limit 1

SQLフィドルの例

于 2012-10-03T15:13:59.653 に答える
0

これは、レートレコードごとに、一致する最新のレートが必要であることを意味します。以下は与えられたデータで機能しますが、本当の答えはこの後に来ます。

select rate.*,
       rmax.hourly_rate,
       rmax.maxdate
from rate join
     (select rmax.*, forhr.hourly_rate
      from (select role, client_company, client_group, client_contact, MAX(date_from) as maxdate
            from rate
            group by role, client_contact, client_group, client_company, role with rollup
           ) rmax join
           rate forhr
           on coalesce(rmax.role, '') = coalesce(forhr.role, '') and
              coalesce(rmax.client_company , '') = coalesce(forhr.client_company, '') and
              coalesce(rmax.client_contact, '') = coalesce(forhr.client_contact, '') and
              coalesce(rmax.client_group, '') = coalesce(forhr.client_group, '') and
              rmax.maxdate = forhr.date_from
     ) rmax
     on coalesce(rmax.role, '') = coalesce(rate.role, '') and
        coalesce(rmax.client_company , '') = coalesce(rate.client_company, '') and
        coalesce(rmax.client_contact, '') = coalesce(rate.client_contact, '') and
        coalesce(rmax.client_group, '') = coalesce(rate.client_group, '')

内部クエリは、日付に関連付けられている最新のレートを取得するためだけのものです。外部クエリは、レートテーブルの各レコードに一致します。

上で何を考えていたのかわかりません。私は自分の思考プロセスに割り込まれたと思います。これにアプローチする最良の方法は、相関サブクエリを使用することだと思います。以下は最大レートを取得します。同じアプローチを使用して、IDと追加情報を取得できます。

select r.*,
       (select hourly_rate
        from rates r2
        where coalesce(r.role, '') = coalesce(r2.role, '') and
              coalesce(r.client_company , '') = coalesce(r2.client_company, '') and
              coalesce(r.client_contact, '') = coalesce(r2.client_contact, '') and
              coalesce(r.client_group, '') = coalesce(r2.client_group, '')
        order by (case when r2.client_contact is not null then 1
                       when r2.client_group is not null then 2
                       when r2.client_company is not null then 3
                       when r2.role is not null then 4
                       else 5
                  end),
                 date_from desc
        limit 1
       ) as most_recent_hourly_rate
from rates r

これは、相関サブクエリを使用して、最も一致する行を取得します。重要なのはorder by句であり、「最も一致する」フィールドから「最も一致しない」フィールド、次に日付の順に並べられます。この場合、それは時給を引き出します。実際には、IDを取得してレートに戻り、レートやその他の情報(日付など)を取得します。

指定された形式では、のデータはratesあなたが言うように構造化されており、たとえばclient_groupとroleを持つ行はなく、他のフィールドはないと想定しています。

于 2012-10-03T15:20:38.170 に答える
0

返されたセットで、オプションの列に基づいてランクを割り当てようとします。ランクが高いほど、一致に最も近く、最大ランクのレコードを取得します...(SQL Fiddleでテスト済み)

クエリの拡張:

SELECT T.*
FROM
(
    SELECT
      rate.*,
      ((CASE WHEN COALESCE(rate.client_company, 1) = COALESCE(newest.client_company, 1)
                       AND rate.client_company = 25  THEN 1
             ELSE 0 END) +
       (CASE WHEN COALESCE(rate.client_group, 1) = COALESCE(newest.client_group, 1)
                      AND rate.client_group = NULL THEN 1
             ELSE 0 END) +
       (CASE WHEN COALESCE(rate.client_contact, 1) = COALESCE(newest.client_contact, 1)
                      AND rate.client_contact = NULL THEN 1
             ELSE 0 END)) AS RANK
      FROM
        rate
      LEFT JOIN rate AS newest
        ON rate.role = newest.role
       AND COALESCE(rate.client_company, 1) = COALESCE(newest.client_company, 1)
       AND COALESCE(rate.client_group, 1) = COALESCE(newest.client_group, 1)
       AND COALESCE(rate.client_contact, 1) = COALESCE(newest.client_contact, 1)
       AND newest.date_from > rate.date_from
     WHERE newest.id IS NULL
       AND rate.role = 3
) T
HAVING T.Rank = MAX(T.Rank)

注:rate.client_company = 25のコードでは、25を会社コードの入力パラメーターに置き換える必要があります。rate.client_group = NULLのコードでは、NULLをクライアントグループIDの入力パラメーターに置き換える必要があります。rate.client_contact= NULLのコードでは、NULLは、rate.roleのあるClientContactIdINコードの入力パラメーターに置き換える必要があります。 = 3、3は、RoleIdの入力パラメーターに置き換える必要があります。

SQl Fiddleで変数を宣言しようとしましたが、宣言できなかったため、上記の値をハードコーディングしました...

于 2012-10-03T15:51:37.550 に答える