顧客の住所のテーブルがあるとしましょう:
CName | AddressLine
-------------------------------
John Smith | 123 Nowheresville
Jane Doe | 456 Evergreen Terrace
John Smith | 999 Somewhereelse
Joe Bloggs | 1 Second Ave
この表では、John Smithのような1人の顧客が複数の住所を持つことができます。 'CName'に重複がある最初の行のみを返すには、このテーブルの選択クエリが必要です。このテーブルでは、3番目を除くすべての行を返す必要があります(または1番目-これら2つのアドレスのいずれでも構いませんが、1つだけを返すことができます)。サーバーが以前に列の値をすでに見たかどうかに基づいてフィルタリングするために、SELECTクエリに追加できるキーワードはありますか?
どのアドレスが使用されても構わないと言う場合、非常に簡単な答えです。
SELECT
CName, MIN(AddressLine)
FROM
MyTable
GROUP BY
CName
たとえば、「挿入」列に従って最初の列が必要な場合、それは別のクエリです
SELECT
M.CName, M.AddressLine,
FROM
(
SELECT
CName, MIN(Inserted) AS First
FROM
MyTable
GROUP BY
CName
) foo
JOIN
MyTable M ON foo.CName = M.CName AND foo.First = M.Inserted
SQL 2k5 +では、次のようなことができます。
;with cte as (
select CName, AddressLine,
rank() over (partition by CName order by AddressLine) as [r]
from MyTable
)
select CName, AddressLine
from cte
where [r] = 1
row_number()
を使用して、行の行番号を取得できます。 over
コマンドを使用します-partition by
句は番号付けをいつ再開するかを指定し、order by
は行番号の順序を選択します。クエリの最後にorder by
を追加した場合でも、番号付け時にover
コマンドの順序を保持します。
select *
from mytable
where row_number() over(partition by Name order by AddressLine) = 1
次のようなrow_numer() over(partition by ...)
構文を使用できます。
select * from
(
select *
, ROW_NUMBER() OVER(PARTITION BY CName ORDER BY AddressLine) AS row
from myTable
) as a
where row = 1
これは、row
という列を作成します。これは、同じCName
を検出するたびに増加するカウンターであり、AddressLine
によってそれらの発生にインデックスを付けます。 where row = 1
を課すことにより、CName
がアルファベット順に最初に来るAddressLine
を選択できます。 order by
がdesc
の場合、CName
がアルファベット順に最後に来るAddressLine
を選択します。
これにより、重複する行ごとに1行が表示されます。また、ビット型の列も提供され、少なくともMS Sql Serverで機能します。
(select cname, address
from (
select cname,address, rn=row_number() over (partition by cname order by cname)
from customeraddresses
) x
where rn = 1) order by cname
代わりにすべての重複を検索する場合は、rn = 1をrn> 1に変更します。これが役立つことを願っています