2016-05-26 15 views
5

İki tablo var, bir "ana" adların ana listesi ve ikinci "senaryo" ana listeden her ad için birden çok senaryo listesidir. . INNER JOIN sorgumun, "senaryo" tablosundaki sütun durumuyla birlikte kimlik ana listesini almasını ancak senaryoyu temel alan en yeni durumu almasını istiyorum. Burada istenen çıkışı ile denedim kod ve tablolar varBaşka bir sütundan maksimum değere dayalı bir sütun üzerinde SQL iç birleştirme

SELECT DISTINCT a.[user], a.ID, a.Name, b.status 
from master a 
INNER JOIN scenario b ON a.ID = b.ID 
WHERE 
    b.scenarioID = (
      SELECT max(scenarioID) FROM scenario c2 WHERE c2.ID=c.ID) 

Usta

ID user Name 
425 John Skyline 
426 John Violin 
427 Joe  Pura 

Senaryo

ID ScenarioID status 
425 1    active 
425 2    active 
425 3    done 
426 1    active 
426 2    active 
427 1    done 

İstenilen çıkış

ID user Name status 
425 John Skyline done 
426 John Violin active 
427 Joe  Pura done 
+0

http://stackoverflow.com/questions/1313120/retrieving-the-last-record-in-each-group sorunu çözmek için farklı yollar vardır, böylece MySQL değil sql server içindir. Ayrıca bu soru son kayda birleştirmeyi içerirken, yinelenen soru sadece bir tablo içinde sonuncuyu almaya çalışıyor. –

cevap

1

Burada genellikle (tabii kilometre değişebilir olsa da) bir alt sorgu daha kolay okunur bulmak bir CTE kullanan biraz farklı formülasyon bu.

declare @Master table 
(
    ID bigint, 
    [user] varchar(16), 
    Name varchar(16) 
); 

declare @Scenario table 
(
    ID bigint, 
    ScenarioID bigint, 
    [status] varchar(16) 
); 

insert @Master values 
    (425, 'John', 'Skyline'), 
    (426, 'John', 'Violin'), 
    (427, 'Joe', 'Pura'); 
insert @Scenario values 
    (425, 1, 'active'), 
    (425, 2, 'active'), 
    (425, 3, 'done'), 
    (426, 1, 'active'), 
    (426, 2, 'active'), 
    (427, 1, 'done'); 

with ReversedScenarioCTE as 
(
    select 
     ID, 
     [status], 
     rowNumber = row_number() over (partition by ID order by ScenarioID desc) 
    from 
     @Scenario 
) 
select 
    M.ID, 
    M.[user], 
    M.Name, 
    S.[status] 
from 
    @Master M 
    inner join ReversedScenarioCTE S on 
     M.ID = S.ID and 
     S.rowNumber = 1; 
3
Sen her değer için en son ararken bir CROSS APPLY ile yapabilirsiniz

:

Select M.ID, M.[User], M.Name, X.Status 
From [Master] M 
Cross Apply 
(
    Select Top 1 S.Status 
    From Scenario S 
    Where S.ID = M.ID 
    Order By S.ScenarioID Desc 
) X 

Yapabileceğin bir başka yolu da ScenarioIDDESC tarafından ID üzerinde ROW_NUMBER()PARTITIONED ve ORDERED ile geçerli:

;With OrderedStatuses As 
(
    Select M.Id, M.[User], M.Name, S.Status, 
      Row_Number() Over (Partition By S.Id Order By S.ScenarioID Desc) RN 
    From [Master] M 
    Join Scenario S On S.Id = M.Id 
) 
Select Id, [User], Name, Status 
From OrderedStatuses 
Where RN = 1 
1

SQL Server 2008 veya daha yenisi varsa, istediğiniz şeyi elde etmek için ROW_NUMBER() işlevini kullanabilirsiniz. Aynı tablonun iki kez sorgulanmasını veya birleştirmeyi gerçekleştirmesini engeller.

SELECT * 
FROM (

      SELECT a.[user] 
        ,a.ID 
        ,a.Name 
        ,b.status 
        ,ROW_NUMBER() OVER (PARTITION BY a.ID ORDER BY b.scenarioID DESC) AS VersionRank 
      from [master] a INNER JOIN scenario b ON a.ID = b.ID 
     ) Result 
WHERE Result.VersionRank = 1 
+0

Bu sorgudaki "DISTINCT" in amacı nedir? –

+0

@JoeFarrell iyi soru Hiçbir şeyden şüpheleniyorum, sadece orijinal sorguyu sorudan kopyalayıp uygun şekilde değiştirdim. –

+1

@JoeFarrell Gereksiz yere kaldırıldı :) –

İlgili konular