2017-08-31 2 views
3

Ich versuche, eine Select-Anweisung zu erstellen, so dass es eine bestimmte in einer Spalte unterscheidet. Ich versuche es so zu machen, dass es nicht mehrere Früchte in jeder ID gibt. Wenn es mehrere Früchte unter einem ID gibt, möchte ich nur 1 zugelassene Frucht über den faulen Früchten verwenden. Wenn nur 1 Frucht unter dieser ID ist, benutze sie.Auswählen bestimmter distinct-Spalte in SQL

SELECT id, fruit, fruitweight, status 
    FROM myfruits 

Raw data from current select  

    id | fruit | fruitweight | status 
    1 | apple |  .2  | approved 
    1 | apple |  .8  | approved 
    1 | apple |  .1  | rotten 
    1 | orange |  .5  | approved 
    2 | grape |  .1  | rotten 
    2 | orange |  .7  | approved 
    2 | orange |  .5  | approved 

Wie es nach Zwang formatiert werden soll

id | fruit | fruitweight | status 
    1 | apple |  .2  | approved 
    1 | orange |  .5  | approved 
    2 | grape |  .1  | rotten 
    2 | orange |  .7  | approved 

ich etwas entlang der Linien von select distinct id,fruit,fruitweight,status from myfruits tun können, aber das wird nur die Duplikate herausnehmen, wenn alle Spalten sind gleich.

+0

Warum verschiedene Früchte haben die gleiche ID? – waka

+0

* nimmt nur die Duplikate heraus, wenn alle Spalten gleich sind * - das ** IST ** die Art, wie 'DISTINCT' funktioniert - wie entworfen –

+1

Wie wählst du diese Apfelreihe aus? – jarlh

Antwort

4

CTE mit Aggregat und Zeilennummer.

declare @YourTable table (id int, fruit varchar(64), fruitweight decimal(2,1),status varchar(64)) 
insert into @YourTable 
values 
(1,'apple',0.2,'approved'), 
(1,'apple',0.8,'approved'), 
(1,'apple',0.1,'rotten'), 
(1,'orange',0.5,'approved'), 
(2,'grape',0.1,'rotten'), 
(2,'orange',0.7,'approved'), 
(2,'orange',0.5,'approved') 


;with cte as(
select 
    id 
    ,fruit 
    ,fruitweight = min(fruitweight) 
    ,[status] 
    ,RN = row_number() over (partition by id, fruit order by case when status = 'approved' then 1 else 2 end) 
from 
    @YourTable 
group by 
    id,fruit,status) 

select 
    id 
    ,fruit 
    ,fruitweight 
    ,status 
from 
    cte 
where RN = 1 

Eine andere Methode, ohne das Aggregat ... Sie unter der Annahme, wollen die erste fruightweight

;with cte as(
select 
    id 
    ,fruit 
    ,fruitweight 
    ,[status] 
    ,RN = row_number() over (partition by id, fruit order by case when status = 'approved' then 1 else 2 end, fruitweight) 
from 
    @YourTable) 

select 
    id 
    ,fruit 
    ,fruitweight 
    ,status 
from 
    cte 
where RN = 1 
1

eine kürzere Version der Lösung des scsimon ohne Aggregate. Wenn Sie SQL Server < 2012 haben, müssen Sie Fall statt iif verwenden.

select 
    id 
    ,fruit 
    ,fruitweight 
    ,status 
from 
(
    select 
     id 
     ,fruit 
     ,fruitweight 
     ,status 
     ,rownum   = row_number() over(partition by id, fruit order by iif(status = 'approved', 0, 1), fruitweight desc) 
    from myfruits 
) x 
where rownum = 1 

EDIT: Ich begann vor scsimon Schreiben bearbeitet enthalten sein Amt eine Version ohne Aggregate ...

+0

Keine Notwendigkeit zu erklären, dass Sie gepostet haben, während ich geantwortet habe. Du hast eine Methode benutzt, die ich nicht gemacht habe! Gute Idee! +1 von mir. – scsimon

3

Eine weitere Option ist die WITH TIES-Klausel.

Beispiel

Select top 1 with ties * 
From YourTable 
Order By Row_Number() over (Partition By id,fruit order by status,fruitweight) 
+1

Müssten Sie nicht auch nach Fruchtgewicht ordern oder möglicherweise inkonsistente Ergebnisse erleiden? Hinweis Apfel ist zweimal mit dem gleichen Status genehmigt aufgeführt. Welches wählen wir? – xQbert

+0

@xQbert Vielleicht. Aber OP erwähnte Fruchtgewicht nicht. Ich werde nur für den Fall hinzufügen. –

Verwandte Themen