3

簡単に参加できる 2 つのテーブルと、問題が発生している 3 番目のテーブルがあります。まず、テーブル:

tbl_customer
id  dt           value  group
a   2013-01-01   10     cavalry
a   2012-06-01   20     lance
a   2011-03-01   10     infantry
b   2013-01-01   20     court
b   2012-07-01   5      maiden
b   2005-06-01   10     chivalry

tbl_title
id  dt_active    dt_inactive   title
a   2001-01-01   2012-01-01    mister
a   2012-01-02   3001-01-01    sir
a   2012-01-02   3001-01-01    king
b   2001-01-01   2012-01-01    miss
b   2012-01-02   3001-01-01    lady
b   2012-01-02   3001-01-01    queen

以下を使用して、特定の ID のタイトルを返すように結合するのは簡単です。

SELECT 
  id, dt, value, title
FROM
  tbl_customer AS cust
INNER JOIN tbl_title AS titles
  ON titles.id = cust.id
  AND dt >= titles.dt_active
  AND dt <= titles.dt_inactive

tbl_customerこれにより、複数の「アクティブな」タイトルがあるいくつかの重複を含むすべての行が返されます。たとえば、 の最初の行tbl_customerは 2 回返されます。1 回は "king" で、もう 1 回は "sir" でtitle.

グループをタイトルにリンクする 3 番目のテーブルがあります。これらの関係を解決するのに役立ちます。

tbl_group
group     title   rank
cavalry   sir     10
lance     king    20
infantry  mister  30
court     lady    10
court     queen   20
maiden    lady    10
chivalry  miss    5

次に、テーブルを結合してタイトルを含め、tbl_group結果を一致するものに制限できます。

SELECT 
  id, dt, value, titles.title
FROM
  tbl_customer AS cust
INNER JOIN tbl_title AS titles
  ON titles.id = cust.id
  AND dt >= titles.dt_active
  AND dt <= titles.dt_inactive
INNER JOIN tbl_group AS group
  ON group.group = cust.group
WHERE
  titles.title = group.title

これは私の問題を大部分解決します。3 番目の表は、に複数の「アクティブな」レコードがある場合のあいまいさを取り除くのに役立ちますtbl_title

ただし、問題があります。3 番目のテーブルには、グループに関連付けられた複数のタイトルを含めることもできます。したがって、最終出力に重複が残る可能性があります。上記の例では、"cavalry" は明確にタイトル "sir" に関連付けられています。ただし、グループ "court" は "lady" または "queen" のいずれかである可能性があり、tbl_title"lady" と "queen" の両方が の日付でアクティブであるため、どちらも役に立ちませんtbl_customer

現時点では、「ランク」以外に選択する方法はありませんtbl_group。「Queen」は「Lady」を20対10で上回っているので、そのタイトルを のエントリに使用したいと思いtbl_customerます。ランクが等しい場合は、 の最初のレコードのみを使用したいと思いtbl_groupます。(これは何らかの内部命令で解決できますか? )

注意が必要なのは、アクティブ/非アクティブのダイナミクスをランクの前に考慮する必要があることです。たとえば、最初tbl_groupにグループごとに 1 つのタイトルをフィルター処理したくありません。これは、日付に基づく一致の可能性を妨げるからです。

tbl_customer理想的には、最初にアクティブ/非アクティブな日付に基づいて、タイトルを表示するエントリごとに 1 行を返す必要があります。次に、 を使用して重複を排除したいと考えていtbl_groupます。tbl_customer最後に、 matching と rank from を使用して、エントリごとに結果を 1 行だけに制限したいと思いtbl_groupます。これは可能ですか?

4

3 に答える 3

1

これを試して:

SELECT *
FROM
(
SELECT 
  id, 
  dt, 
  value, 
  titles.title, 
  group.rank MAX(rank) OVER(PARTITION BY cust.id) AS MAX_RANK
FROM
  tbl_customer AS cust
INNER JOIN tbl_title AS titles
  ON titles.id = cust.id
  AND dt BETWEEN titles.dt_active AND titles.dt_inactive
INNER JOIN tbl_group AS group
  ON group.group = cust.group
WHERE
  titles.title = group.title
) AS RESULTS
WHERE rank = MAX_RANK

ウィンドウ関数MAX(rank) OVER(PARTITION BY cust.id)は、ID ごとに最大ランクを取得します。次に、行をフィルタリングして、ランクがその顧客の最大ランクである行のみを返します。

于 2013-09-18T15:05:33.763 に答える
0
SELECT  *
FROM    (
        SELECT  *,
                ROW_NUMBER() OVER (PARTITION BY g.group, g.title ORDER BY g.rank DESC) rn
        FROM    tbl_customer с
        JOIN    tbl_title t
        ON      t.id = c.id
                AND c.dt BETWEEN t.dt_active AND t.dt_inactive
        JOIN    tbl_group g
        ON      g.[group] = c.[group]
                AND g.title = c.title
        ) q
WHERE   rn = 1
于 2013-09-18T15:06:05.560 に答える