• Status: Solved
  • Priority: Low
  • Security: Public
  • Views: 30
  • Last Modified:

Get Distinct TOP record from multiple columns

Hello, all;
(SQL Server 2016)

I need to get the top record for all duplicate numbers.
When I try a distinct on the itemID, it gives me the bottom record and skips a lot of rows for some reason.
(And yes, I have also tried MIN and MAX on this as well, and it still does not work.)

Here is a sample of the data. I need to return the TOP rows, from all the duplicates.
As it is it Front cover.
I could do  
caption='Front Cover'
However, there are some entries that do not have a cover, and their entry is NULL.

ItemNo	CloserLookID	Caption
2	00000002	Front cover
2	00000002	Back cover
118	00000118	Front cover
118	00000118	Back cover
130	00000130	FRONT COVER
130	00000130	BACK COVER
130	00000130	P2
130	00000130	P6
202	00000202	Front cover
202	00000202	Back cover
202	00000202	Preface
202	00000202	Color page 1
202	00000202	Color page 2
220	00000220	Front Cover
220	00000220	Table of Contents
220	00000220	Introduction
220	00000220	Sample Page 1
220	00000220	Sample Page 2
220	00000220	Back Cover
284	00000284	Front cover
284	00000284	Back cover
290	00000290	FRONT COVER
290	00000290	BACK COVER
290	00000290	MUSIC SAMPLE
384	00000384	Front Cover
384	00000384	Back Cover
384	00000384	Contents
384	00000384	Performer credits
385	00000385	Front Cover
385	00000385	Back Cover

Open in new window


Thanks
Carrkiss
0
Wayne Barron
Asked:
Wayne Barron
1 Solution
 
Scott PletcherSenior DBACommented:
You need to define "TOP".  SQL has no direct idea of the "first" row that was inserted to the table.

If the ItemNo and CloserLookId are the same, you can't guarantee which row you get back except by ordering on the Caption.
0
 
ste5anSenior DeveloperCommented:
hmm, despite how you define your order for TOP, using ROWNUMBER() is a common approach:

DECLARE @Sample TABLE
    (
        ItemNo INT ,
        CloserLookID INT ,
        Caption NVARCHAR(255)
    );

INSERT INTO @Sample ( ItemNo ,
                      CloserLookID ,
                      Caption )
VALUES ( 2, 00000002, 'Front cover' ) ,
       ( 2, 00000002, 'Back cover' ) ,
       ( 118, 00000118, 'Front cover' ) ,
       ( 118, 00000118, 'Back cover' ) ,
       ( 130, 00000130, 'FRONT COVER' ) ,
       ( 130, 00000130, 'BACK COVER' ) ,
       ( 130, 00000130, 'P2' ) ,
       ( 130, 00000130, 'P6' ) ,
       ( 202, 00000202, 'Front cover' ) ,
       ( 202, 00000202, 'Back cover' ) ,
       ( 202, 00000202, 'Preface' ) ,
       ( 202, 00000202, 'Color page 1' ) ,
       ( 202, 00000202, 'Color page 2' ) ,
       ( 220, 00000220, 'Front Cover' ) ,
       ( 220, 00000220, 'Table of Contents' ) ,
       ( 220, 00000220, 'Introduction' ) ,
       ( 220, 00000220, 'Sample Page 1' ) ,
       ( 220, 00000220, 'Sample Page 2' ) ,
       ( 220, 00000220, 'Back Cover' ) ,
       ( 284, 00000284, 'Front cover' ) ,
       ( 284, 00000284, 'Back cover' ) ,
       ( 290, 00000290, 'FRONT COVER' ) ,
       ( 290, 00000290, 'BACK COVER' ) ,
       ( 290, 00000290, 'MUSIC SAMPLE' ) ,
       ( 384, 00000384, 'Front Cover' ) ,
       ( 384, 00000384, 'Back Cover' ) ,
       ( 384, 00000384, 'Contents' ) ,
       ( 384, 00000384, 'Performer credits' ) ,
       ( 385, 00000385, 'Front Cover' ) ,
       ( 385, 00000385, 'Back Cover' );

WITH Ordered
AS ( SELECT * ,
            ROW_NUMBER() OVER ( PARTITION BY S.Caption
                                ORDER BY S.ItemNo ,
                                         S.CloserLookID ) AS RN
     FROM   @Sample S )
SELECT *
FROM   Ordered O
WHERE  O.RN = 1;

Open in new window

0
 
Wayne BarronAuthor, Web DeveloperAuthor Commented:
@Ste5an
Does not work.
This is what I get, running your SQL Example.

ItemNo	CloserLookID	Caption	RN
2	2	Back cover	1
202	202	Color page 1	1
202	202	Color page 2	1
384	384	Contents	1
2	2	Front cover	1
220	220	Introduction	1
290	290	MUSIC SAMPLE	1
130	130	P2	1
130	130	P6	1
384	384	Performer credits	1
202	202	Preface	1
220	220	Sample Page 1	1
220	220	Sample Page 2	1
220	220	Table of Contents	1

Open in new window


another choice would be.
To run this
Caption = 'Cover' or caption='Front Cover'

This seems to work, I will just have to go through the entire list of over 100,000 records to make sure all have either a
Front Cover (OR) Cover

It is a pain working with someone else's data.
0
Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

 
ste5anSenior DeveloperCommented:
Well, what is your desired output from your sample data? It's not clear what you want to get.. post it.
0
 
awking00Commented:
I don't think this should be abandoned so quickly. Just a little more information is needed (expected results from the sample would be most helpful). Are you saying that a caption value of 'FrontCover', 'Cover',' Sample Page 1', or 'Box Front' should be deemed to be the "TOP"?
Perhaps something like the following would work.
with cte as
(select ItemNo, CloserLookID, Caption,
 case when lower(Caption) = 'front cover' or lower(Caption) = 'cover' or lower(Caption) = 'sample page 1' or lower(Caption) = 'box front' then 1
          else 2
 end orderno
 from sample),
cte2 as
(select ItemNo, CloserLookID, Caption,
 row_number() over (partition by ItemNo order by orderno) rowno
 from cte
 where orderno = 1)
select temNo, CloserLookID, Caption
from cte2
where rowno = 1;
0
 
Wayne BarronAuthor, Web DeveloperAuthor Commented:
@awking00
Unfortunately, the data has the values in CAPTION all over the place.
(The design of this database reminds me of when I first started learning this stuff 18+years ago. It is a mess)
I could order it, but the data gets updates once a week, and that would be a little bit to much work.
Considering there are over 80+ thousand records that I have to update every single week, once this site goes live.

So, I am going to leave it at how I have it set right now.
Which is, I created a REPLACE script that runs through the table once I have it imported, and I change all the instances to 'front cover'
So, all I have to do now is simply run the script and grab just the front Cover, and I get all the data that is there for the query.

thanks for the added information, it is much appreciated.
Wayne
0
 
Wayne BarronAuthor, Web DeveloperAuthor Commented:
I will have to go with the choice I chose, as the Front Cover, seems to NOT always be at the top.
So, I have to look at
Caption= Front Cover, Cover, Sample Page 1, Box Front

So, it is a pain, but simply to work with, in order to get the results that are needed.

Thanks for the attempted assistance from both Experts.
0

Join & Write a Comment

Featured Post

Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now