1

このデータを含む行がある場合:

ID |Name        |ContractType|
---|------------|------------|
 1 |Aaron Shatz | 6-month    |
 2 |Jim Smith   |12-month    |
 3 |Jim Smith   | 6-month    |
 4 |Mark Johnson|12-month    |

Id を使用して使用するレコードを決定することはできません: ContractTypeを使用する必要があります。テーブルからすべてのレコードを選択したいのですが、名前の値が同じレコードが複数ある場合は、12 か月契約のレコードを選択したいと考えています。

クエリの結果は次のようになります。

ID |Name        |ContractType|
---|------------|------------|
 1 |Aaron Shatz | 6-month    |
 2 |Jim Smith   |12-month    |
 4 |Mark Johnson|12-month    |
4

2 に答える 2

5

ハードコード版

このソリューションでは、契約タイプが 6 か月と 12 か月の 2 つだけであることを前提としています。dynamicバージョンは一番下までスクロールしてください。

SQL Fiddle でデモを表示するには、ここをクリックしてください。

スクリプト:

CREATE TABLE contracts
(
        id              INT         NOT NULL IDENTITY
    ,   name            VARCHAR(30) NOT NULL
    ,   contracttype    VARCHAR(30) NOT NULL
);

INSERT INTO contracts (name, contracttype) VALUES
    ('Aaron Shatz',     '6-month'),
    ('Jim Smith',       '12-month'),
    ('Jim Smith',       '12-month'),
    ('Mark Johnson',    '12-month'),
    ('John Doe',        '6-month'),
    ('Mark Johnson',    '6-month'),
    ('Aaron Shatz',     '6-month');

SELECT id   
    ,   name
    ,   contracttype
FROM
(
    SELECT  id  
        ,   name
        ,   contracttype
        ,   ROW_NUMBER() OVER(PARTITION BY name ORDER BY contracttype) AS rownum
    FROM    contracts
) T1 
WHERE rownum = 1
ORDER BY id;

出力:

id  name          contracttype
--  ------------  ------------
1   Aaron Shatz   6-month
2   Jim Smith     12-month
4   Mark Johnson  12-month
5   John Doe      6-month

動的バージョン

これにより、コントラクト型データがシーケンス列を持つ独自のテーブルに移動されます。コントラクト タイプの順序付けに基づいて、クエリは適切なレコードをフェッチします。

SQL Fiddle でデモを表示するには、ここをクリックしてください。

スクリプト:

CREATE TABLE contracts
(
        id              INT         NOT NULL IDENTITY
    ,   name            VARCHAR(30) NOT NULL
    ,   contracttypeid  INT         NOT NULL
);

CREATE TABLE contracttypes 
(
        id              INT         NOT NULL IDENTITY
    ,   contracttype    VARCHAR(30) NOT NULL
    ,   sequence        INT         NOT NULL 
)

INSERT INTO contracttypes (contracttype, sequence) VALUES
    ('12-month', 1),
    ('6-month',  3),
    ('15-month',  2);

INSERT INTO contracts (name, contracttypeid) VALUES
    ('Aaron Shatz',     2),
    ('Jim Smith',       2),
    ('Jim Smith',       3),
    ('Mark Johnson',    1),
    ('John Doe',        2),
    ('Mark Johnson',    2),
    ('Aaron Shatz',     2);

SELECT  id  
    ,   name
    ,   contracttype
FROM
(
    SELECT  c.id    
        ,   c.name
        ,   ct.contracttype
        ,   ROW_NUMBER() OVER(PARTITION BY name ORDER BY ct.sequence) AS rownum
    FROM            contracts           c
    LEFT OUTER JOIN contracttypes       ct
    ON              c.contracttypeid    = ct.id
) T1 
WHERE rownum = 1
ORDER BY id;

出力:

id  name          contracttype
--  ------------  ------------
1   Aaron Shatz   6-month
3   Jim Smith     15-month
4   Mark Johnson  12-month
5   John Doe      6-month
于 2012-04-30T21:24:20.567 に答える
4

これが機能するのは、OP が 2 つの契約タイプのみが可能であることを確認したためであり、OP が (契約者ごとに) 希望するものはたまたまアルファベット順に最初に注文するものです。したがって、いくつかの偶然により、このソリューションは簡単になります。

;WITH x AS
(
  SELECT ID, Name, ContractType, rn = ROW_NUMBER() OVER
    (PARTITION BY Name ORDER BY ContractType)
  FROM dbo.some_table
)
SELECT ID, Name, ContractType 
  FROM x
  WHERE rn = 1
  ORDER BY ID;

これをより動的にする必要がある場合は、次のように言うことができると思います。

DECLARE @PreferredContractType VARCHAR(32);
SET @PreferredContractType = '12-month';

;WITH x AS
(
  SELECT ID, Name, ContractType, rn = ROW_NUMBER() OVER
    (PARTITION BY Name ORDER BY CASE ContractType
      WHEN @PreferredContractType THEN 1 ELSE 2 END
    )
  FROM dbo.some_table
)
SELECT ID, Name, ContractType 
  FROM x
  WHERE rn = 1
  ORDER BY ID;
于 2012-04-30T21:18:51.573 に答える