简体   繁体   中英

SQL Server : select distinct records with inner join and where clause

Friends I am stuck in a stored procedure. I am unable to display distinct records.

I have a name USERS and Photos . Both are inner join using userID .

Since the table Photos has multiple records the search result is repeated. Friends can you help me fix this please?

Stored procedure:

ALTER PROCEDURE dbo.homesearch
   @gender varchar(6),
   @age int,
   @age2 int,
   @religion varchar(50),
   @status varchar(11),
   @Country varchar(50),
   @City varchar(50)
AS
   SELECT 
       users.userID, photos.filename, users.userName,
       users.FirstName, users.LastName, users.nationality, 
       users.Country, users.City, users.age, users.status 
   FROM 
       users 
   INNER JOIN 
       photos ON users.userID = photos.userID
   WHERE 
      (users.age >= @age) AND (users.age <= @age2) 
      AND (users.gender = @gender) AND (users.religion = @religion) 
      AND (users.status = @status) AND (users.Country = @Country) 
      AND (users.City = @City)

   RETURN

You can do something like this using CROSS APPLY

SELECT u.userID
      ,u.userName
      ,P.filename
      ,u.FirstName
      ,u.LastName
      ,u.nationality 
      ,u.Country
      ,u.City
      ,u.age
      ,u.status 

FROM  users u
        CROSS APPLY
                  (
                  SELECT TOP 1 photos.filename
                  FROM photos 
                  WHERE u.userID = userID
                  ORDER BY photos.SomeColumn   --<-- Pick a column here
                  )p
WHERE (u.age >= @age)      AND (u.age <= @age2) 
AND   (u.gender = @gender) AND (u.religion = @religion) 
AND   (u.status = @status) AND (u.Country = @Country) 
AND   (u.City = @City)

Pick a column by which you want to decide which TOP 1 filename you want to pick from Photos table for each user in users table.

Or using CTE

;With P_CTE
AS
 (
 SELECT TOP UserID, photos.filename,
        rn = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY UserID)
 FROM photos
 )
SELECT users.userID, P_CTE.filename, users.userName,
       users.FirstName, users.LastName, users.nationality, 
       users.Country, users.City, users.age, users.status 
FROM   users INNER JOIN  P_CTE 
ON     users.userID = P_CTE.userID
WHERE  (users.age >= @age) AND (users.age <= @age2) 
AND    (users.gender = @gender) AND (users.religion = @religion) 
AND    (users.status = @status) AND (users.Country = @Country) 
AND    (users.City = @City)
AND    P_CTE.rn = 1

modify Your select query by :-

SELECT users.userID, photos.filename, users.userName,
   users.FirstName, users.LastName, users.nationality, 
   users.Country, users.City, users.age, users.status 
FROM users INNER JOIN photos 
    ON users.userID = photos.userID
WHERE (users.age >= @age) AND (users.age <= @age2) 
    AND (users.gender = @gender) AND (users.religion = @religion) 
    AND (users.status = @status) AND (users.Country = @Country) 
    AND (users.City = @City) 
GROUP BY users.userID, photos.filename, users.userName,
   users.FirstName, users.LastName, users.nationality, 
   users.Country, users.City, users.age, users.status

and it will return unique results.

SELECT users.userID, photos.filename, users.userName,
   users.FirstName, users.LastName, users.nationality, 
   users.Country, users.City, users.age, users.status 
FROM users INNER JOIN (SELECT DISTINCT userID FROM photos) AS P 
ON users.userID = P.userID

The idea here is to reduce the entries in your Photos table since there are many photos for each user. In my example I'm using max(filename) to get the one with longest name but you can use other criteria here:

SELECT users.userID, P.filename, users.userName,
   users.FirstName, users.LastName, users.nationality, 
   users.Country, users.City, users.age, users.status 
FROM users INNER JOIN 
 (SELECT userID, max(filename) as filename 
  FROM photos
  GROUP BY userID) AS P 
ON users.userID = P.userID
WHERE (users.age >= @age) AND (users.age <= @age2) 
   AND (users.gender = @gender) AND (users.religion = @religion) 
   AND (users.status = @status) AND (users.Country = @Country) 
   AND (users.City = @City)

Please clear some points Ali.

Your data is showing something like..

userID      userName ......... filename
1           ABC                c:/phot1.png
1           ABC                c:/phot2.png
1           ABC                c:/phot2.png

If i am correct, then their is two possible ways to show your data to make your records distinct.

First

  userID      userName ......... filename
    1           ABC                c:/phot1.png,c:/phot2.png,c:/phot2.png

This can be achieved by using for xml path('') OR COALESCE

Second
Show only one photo like:

userID      userName ......... filename
        1           ABC                c:/photo1.png

This can be achieved by applying some condition for photo.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM