多数の結合を持つ多数の大きなテーブル(行と列)に対してクエリを実行していますが、テーブルの1つに重複したデータ行があり、クエリに問題が発生しています。これは別の部門からの読み取り専用のリアルタイムフィードであるため、そのデータを修正することはできませんが、クエリからの問題を防止しようとしています。
それを考えると、このクラップデータを左の結合として適切なクエリに追加する必要があります。データセットは次のようになります。
IDNo FirstName LastName ...
-------------------------------------------
uqx bob smith
abc john willis
ABC john willis
aBc john willis
WTF jeff bridges
sss bill doe
ere sally abby
wtf jeff bridges
...
(約2ダースの列と10万行)
私の最初の本能は、約80K行を与えた個別の実行です。
SELECT DISTINCT P.IDNo
FROM people P
しかし、次のことを試みると、すべての行が返されます。
SELECT DISTINCT P.*
FROM people P
OR
SELECT
DISTINCT(P.IDNo) AS IDNoUnq
,P.FirstName
,P.LastName
...etc.
FROM people P
次に、すべての列でFIRST()集計関数を実行することを考えましたが、それも間違っています。構文的にここで何か間違ったことをしていますか?
更新:注:これらのレコードは、上記のIDの非キー/非インデックスフィールドに基づいて重複しています。 IDはテキストフィールドであり、値は同じですが、問題の原因となっている他のデータとは異なるケースです。
間違ったことをしていましたが、重要な列だけで最初にネストされた選択を実行し、「ユニークな」データのゴミの列が私の良いデータを破損しないように明確な選択を行う必要がありました。以下は問題を解決したように見えます...しかし、私は後で完全なデータセットで試みます。
SELECT DISTINCT P2.*
FROM (
SELECT
IDNo
, FirstName
, LastName
FROM people P
) P2
要求されたプレイデータを次に示します。 http://sqlfiddle.com/#!3/050e0d/
CREATE TABLE people
(
[entry] int
, [IDNo] varchar(3)
, [FirstName] varchar(5)
, [LastName] varchar(7)
);
INSERT INTO people
(entry,[IDNo], [FirstName], [LastName])
VALUES
(1,'uqx', 'bob', 'smith'),
(2,'abc', 'john', 'willis'),
(3,'ABC', 'john', 'willis'),
(4,'aBc', 'john', 'willis'),
(5,'WTF', 'jeff', 'bridges'),
(6,'Sss', 'bill', 'doe'),
(7,'sSs', 'bill', 'doe'),
(8,'ssS', 'bill', 'doe'),
(9,'ere', 'sally', 'abby'),
(10,'wtf', 'jeff', 'bridges')
;
distinct
はnot関数です。常に選択リストのall列で動作します。
あなたの問題は、ウィンドウ関数を使用して簡単に解決できる典型的な「グループごとの最大N」問題です。
select ...
from (
select IDNo,
FirstName,
LastName,
....,
row_number() over (partition by lower(idno) order by firstname) as rn
from people
) t
where rn = 1;
order by
句では、どの複製を選択するかを選択できます。
上記は左結合で使用できます。
select ...
from x
left join (
select IDNo,
FirstName,
LastName,
....,
row_number() over (partition by lower(idno) order by firstname) as rn
from people
) p on p.idno = x=idno and p.rn = 1
where ...
ID列(PeopleID)を追加し、相関サブクエリを使用して各値の最初の値を返します。
SELECT *
FROM People p
WHERE PeopleID = (
SELECT MIN(PeopleID)
FROM People
WHERE IDNo = p.IDNo
)
重複行の性質によっては、必要なのはそれらの列で大文字と小文字を区別することだけのように見えます。これらの列に照合順序を設定すると、次のようになります。
SELECT DISTINCT p.IDNO COLLATE SQL_Latin1_General_CP1_CI_AS, p.FirstName COLLATE SQL_Latin1_General_CP1_CI_AS, p.LastName COLLATE SQL_Latin1_General_CP1_CI_AS
FROM people P
慎重に検討した後、このディレマにはいくつかの異なる解決策があります。
Aggregate Everything各列で集計を使用して、最大または最小のフィールド値を取得します。これは、2つの部分的に記入されたレコードを取り、データを「マージ」するため、私がやっていることです。
http://sqlfiddle.com/#!3/59cde/1
SELECT
UPPER(IDNo) AS user_id
, MAX(FirstName) AS name_first
, MAX(LastName) AS name_last
, MAX(entry) AS row_num
FROM people P
GROUP BY
IDNo
Get First(またはLast record)
http://sqlfiddle.com/#!3/59cde/2
-- ------------------------------------------------------
-- Notes
-- entry: Auto-Number primary key some sort of unique PK is required for this method
-- IDNo: Should be primary key in feed, but is not, we are making an upper case version
-- This gets the first entry to get last entry, change MIN() to MAX()
-- ------------------------------------------------------
SELECT
PC.user_id
,PData.FirstName
,PData.LastName
,PData.entry
FROM (
SELECT
P2.user_id
,MIN(P2.entry) AS rownum
FROM (
SELECT
UPPER(P.IDNo) AS user_id
, P.entry
FROM people P
) AS P2
GROUP BY
P2.user_id
) AS PC
LEFT JOIN people PData
ON PData.entry = PC.rownum
ORDER BY
PData.entry
これを試して
SELECT *
FROM people P
where P.IDNo in (SELECT DISTINCT IDNo
FROM people)