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

SQL - "DISTINCT" на основе только нескольких столбцов?

У меня есть база данных с двумя таблицами. Одна из таблиц содержит пользователей, другая содержит адреса для этих пользователей. Каждый пользователь может иметь несколько адресов (хотя каждый адрес привязан только к одному пользователю.)

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

Вот пример результата поиска:

tst  olix  Chicago  IL  USA
tst  olix  Los Angeles  CA  USA
tst2 olix2 Houston  TX USA

Мне нужно, чтобы поиск был таким, что он возвращает только 2 строки, а не 3.

Любые идеи?

SELECT DISTINCT
    Users.Firstname, Users.Surname, Users.UserId, 
    Users.Recommendations, Addresses.City, Addresses.Region,
    Addresses.Country
FROM
    Users INNER JOIN
    Addresses ON FT_TBL.UserId = Addresses.UserId
ORDER BY
    Users.Recommendations
4b9b3361

Ответ 1

Если Addresses имеет поле ID:

(обновлено для SQL-Server)

SELECT 
    Users.Firstname,
    Users.Surname,
    Users.UserId, 
    Users.Recommendations,
    Addresses.City,
    Addresses.Region,
    Addresses.Country
FROM
    Users INNER JOIN
    Addresses ON Users.UserId = Addresses.UserId
WHERE Addresses.ID = 
    ( SELECT TOP 1 A2.ID
      FROM Addresses AS A2
      WHERE Users.UserId = A2.UserId
    )
ORDER BY
    Users.Recommendations

Использование функций окна и ранжирования SQL-Server:

SELECT 
    Users.Firstname,
    Users.Surname,
    Users.UserId, 
    Users.Recommendations,
    Addresses.City,
    Addresses.Region,
    Addresses.Country
FROM
    Users INNER JOIN
     ( SELECT *
            , ROW_NUMBER() OVER (PARTITION BY UserID) AS rn
       FROM Addresses
     ) AS Addresses ON Users.UserId = Addresses.UserId
                    AND Addresses.rn = 1
ORDER BY
    Users.Recommendations

Ответ 2

Вероятно, вам нужно использовать GROUP BY вместо DISTINCT.

Отправьте свой запрос сейчас, и я помогу вам больше.

В качестве альтернативы, если вы просто хотите вернуть первый адрес, это другой запрос. Нужно ли возвращать адрес? Какие данные вам нужны? Что означает "первое" в этом контексте? Как упорядочиваются данные?

Произвольно вы можете сделать что-то вроде этого (untested), в зависимости от вашей БД:

SELECT 
    userID
    , FIRST(address)
FROM
    yourTable
GROUP BY
    userID

Ответ 3

SELECT Name, MAX(Address), MAX(other field)...
FROM MyTable
GROUP BY Name

Дает вам одну строку за Name.

Ответ 4

Предполагая, что таблица адресов имеет столбец id:

select p.fname, p.lname, a.state, a.country
from person p
join address a on a.personid = p.personid
where not exists
    (select *
    from address a2
    where a2.personid = a.personid
      and a2.addressid < a.addressid)

Мой запрос возвращает всех людей с адресами. Предложение exists() используется для определения того, что возвращенный адрес имеет самый низкий адрес, назначенный человеку. Результат будет содержать только 1 адрес на человека.


EDIT: Другой способ сделать это с помощью top, который не был показан другими:

select p.fname, p.lname, a.state, a.country
from person p
join address a on a.addressid =
    (select top 1 a2.addressid
    from address a2
    where a2.personid = p.personid)

Это должно быть очень эффективным, так как вложенный запрос будет замыкаться по первому адресу, найденному для каждого человека.

Ответ 5

Попробуйте совокупность:

SELECT user, address FROM users
JOIN addresses ON (users.user_id = addresses.user_id)
GROUP BY user;