2011-07-22 22 views
19

İki tablo içeren bir veritabanım var. Tablolardan biri kullanıcı içerir, diğeri bu kullanıcılar için adresler içerir. Her kullanıcı birden fazla adrese sahip olabilir (her adres yalnızca bir kullanıcıya bağlı olsa da).SQL - 'DISTINCT' sadece bazı sütunlara dayanıyor mu?

Her kullanıcı için birden fazla adrese sahip olsa bile yalnızca bir giriş döndüren bir arama oluşturmak istiyorum. Aramanın hangi adresi geri çektiği önemli değildir - arama ilk önce ne olursa olsun yeterlidir.

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

Ben sadece 2 satır yerine 3.

Herhangi bir fikir verir şekilde olması araması gerekir: Burada

bir örnek arama sonucudur?

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

neler SQL Server veya Access kullanıyor musunuz? –

+0

Eğer bu postgresql ise, DISTINCT ON sözdizimini kullanabilirsiniz. – sage88

cevap

8

Addresses bir ID alan varsa:

(SQL Server için güncellenmiş)

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'ın penceresini kullanarak ve sıralama işlevleri:

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

Bu, kullandığım karşılaştırmadan daha kullanışlı görünüyor. Ancak, microsoft sql'in LIMIT'i yok. – Oliver

+1

SQL-Server 'TOP' –

+0

@Oliver'e sahiptir: Ayrıca bu durumda kullanışlı olması gereken pencere işlevleri. –

7

Muhtemelen bu durumda GROUP BY yerine DISTINCT kullanmak gerekir.

Sorunuz şimdi gönderin ve size daha fazla yardımcı olalım.

Alternatif olarak, ilk adresini döndürmek istiyorsanız, bu tamamen farklı bir sorgudur. Adresi geri vermek zorunda mı? Hangi verilere ihtiyacınız var? Bu bağlamda "ilk" ne demektir? Veriler nasıl sıralanıyor?

Keyfi size DB bağlı olarak, bu (denenmemiş) gibi bir şey yapabileceğini:

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

Nihayetinde bir yer araması olmasını istiyorum ve sonuç geri çekildiğinde belirli bir yere en yakın yer. Şu anda sitenin tasarımında çalışırken bir şeyleri geri çekmeyi istiyorum. Cevabınız – Oliver

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

Name başına size bir satır verecek.

+1

+1 cevabım, benimki gibi bazı keyfi siparişlere bağlıdır. OP açıklığa kavuşturmalıdır. – Matthew

+3

@Matthew - soruda kimin alacağı umrumda değil diyor. Alanların birbiriyle ilişkili olup olmadığına inanıyorum (yani Adres1, Şehir, Eyalet, Posta) - yanlış durum/adres kombinasyonunu alabileceksiniz. – JNK

+0

Tam olarak: "Los Angeles | IL | USA'. –

0

bir agrega deneyin:

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

adres tablosu id sütunu vardır varsayarsak:

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) 

Benim sorgu adresleri ile bütün insanları döndürür. exists() cümlesi, döndürülen adresin kişiye atanan en düşük adres kimliğine sahip olduğunu belirlemek için kullanılır. Sonuç kişi başına sadece 1 adres içerecektir.


DÜZENLEME:

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) 

Bu iç içe sorgu olarak çok etkili olmalıdır ilk adresine kısa devre her bulundu olacaktır: başkaları tarafından gösterilmemiştir bu kullanarak top yapmanın bir başka yolu kişi.

+0

Teşekkürler, bunu bulmak için en kolay bir tane buldum. Benim kullanıcı/adres kimlikleri sadece sayılar yerine alfasayısal olmasına rağmen çalışır gibi görünüyor. Bu yöntemde yavaş olan herhangi bir sorun var mı? Her bir sonuç için ikinci bir ikinci arama yapması gerekiyor. – Oliver

+0

Ne olursa olsun, sorguda adres tablosuna iki kez göndermeniz gerektiğini düşünüyorum. "Üst", yerküp'ün aslında benim varlığım() 'dan daha hızlı olabileceğini seçer. Ancak, kesin bir şekilde söylemek zor ve bu tekniği çok fazla yavaşlamadan çok kez kullanmadan kullandım. – dana

İlgili konular