Подтвердить что ты не робот

SQL Left Только первое совпадение

У меня есть запрос против большого числа больших таблиц (строк и столбцов) с несколькими объединениями, однако в одной из таблиц есть несколько повторяющихся строк данных, вызывающих проблемы для моего запроса. Поскольку это только чтение в реальном времени из другого отдела, я не могу исправить эти данные, однако я пытаюсь предотвратить проблемы в моем запросе.

Учитывая, что мне нужно добавить эти данные дерьма в качестве левого соединения к моему хорошему запросу. Набор данных выглядит так:

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 десятков столбцов и 100 тыс. строк)

Мой первый инстинкт состоял в том, чтобы выполнить отчет, который дал мне около 80 тыс. строк:

SELECT DISTINCT P.IDNo
FROM people P

Но когда я пытаюсь сделать следующее, я возвращаю все строки:

SELECT DISTINCT P.*
FROM people P

ИЛИ

SELECT 
    DISTINCT(P.IDNo) AS IDNoUnq 
    ,P.FirstName
    ,P.LastName
    ...etc.    
FROM people P

Тогда я подумал, что я буду выполнять агрегатную функцию FIRST() во всех столбцах, однако это тоже не так. Синтаксически я делаю что-то неправильно здесь?

Update: Просто хотелось бы отметить: эти записи являются дубликатами на основе неиндексного/неиндексированного поля идентификатора, указанного выше. Идентификатор - это текстовое поле, которое хотя и имеет одно и то же значение, это другой случай, чем другие данные, вызывающие проблему.

4b9b3361

Ответ 1

Оказывается, я делал это неправильно, мне нужно было выполнить вложенный выбор сначала только из важных столбцов и сделать отдельный выбор, чтобы предотвратить столбцы корзины "уникальных" данных от развращения моих хороших данных. Следующее, похоже, решило проблему... но позже я попробую полный набор данных.

SELECT DISTINCT P2.*
FROM (
  SELECT
      IDNo
    , FirstName
    , LastName
  FROM people P
) P2

Ниже приведены некоторые данные воспроизведения: http://sqlfiddle.com/#!3/050e0d/3

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')
;

Ответ 2

distinct не функция. Он всегда работает со всеми столбцами списка выбора.

Ваша проблема - типичная проблема "наибольшего 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 ...

Ответ 3

Добавьте столбец идентификатора (PeopleID), а затем используйте коррелированный подзапрос, чтобы вернуть первое значение для каждого значения.

SELECT *
FROM People p
WHERE PeopleID = (
    SELECT MIN(PeopleID) 
    FROM People 
    WHERE IDNo = p.IDNo
)

Ответ 4

В зависимости от характера повторяющихся строк, похоже, что все, что вам нужно, - это чувствительность к регистру для этих столбцов. Настройка сортировки по этим столбцам должна быть следующей:

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

http://msdn.microsoft.com/en-us/library/ms184391.aspx

Ответ 5

После тщательного рассмотрения эта диллема имеет несколько разных решений:

Совокупное все Используйте агрегат для каждого столбца, чтобы получить наибольшее или минимальное значение поля. Это то, что я делаю, так как он принимает 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

Получить первую (или последнюю запись)

http://sqlfiddle.com/#!3/59cde/23

-- ------------------------------------------------------
-- 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

Ответ 6

Попробуйте это

 SELECT *
 FROM people P 
 where P.IDNo in (SELECT DISTINCT IDNo
              FROM people)