2016-09-19 4 views
0

Gibt es eine Möglichkeit, eine reihenbasierte Bedingung in Left Join zu schreiben.Zeilenbasierte Bedingung in linker Verknüpfung

Wenn eine Zeile basierend auf der Spaltenbedingung nicht existiert, sollte sie die nächste erste Zeile übernehmen.

ich die Struktur unten haben,

create table Report 
(
    id int, 
    name varchar(10) 
) 

create table ReportData 
(
    report_id int references report(id), 
    flag bit, 
    path varchar(50) 
) 

insert into Report values (1, 'a'); 
insert into Report values (2, 'b'); 
insert into Report values (3, 'c'); 

insert into ReportData values (1, 0, 'xx'); 
insert into ReportData values (2, 0, 'yy'); 
insert into ReportData values (2, 1, 'yy'); 
insert into ReportData values (3, 1, 'zz'); 
insert into ReportData values (3, 1, 'mm'); 

Ich brauche eine Ausgabe wie

1 a 0 xx 
2 b 0 yy 
3 c 1 zz 
+0

müssen Sie eindeutige Zeilen für jede ID in Berichtstabelle? –

+0

Was meinen Sie mit "Wenn eine Zeile basierend auf der Spaltenbedingung nicht existiert". in deinem obigen Beispiel? – GauravKP

Antwort

1

Sie ROW_NUMBER dafür verwenden können:

;WITH ReportDate_Rn AS (
    SELECT report_id, flag, path, 
      ROW_NUMBER() OVER (PARTITION BY report_id ORDER BY path) AS rn 
    FROM ReportDate 
) 
SELECT t1.id, t1.name, t2.flag, t2.path 
FROM Report AS t1 
JOIN ReportDate_Rn AS t2 ON t1.id = t2.report_id AND t2.rn = 1 

Die obige Abfrage in Bezug auf als zuerst Aufzeichnung von jedem report_id s Läuse, die mit der alphabetisch kleinstepath. Sie können die ORDER BY Klausel der ROW_NUMBER() Fensterfunktion beliebig ändern.

0
SELECT id,name,flag,path 
FROM 
(

SELECT Report.id,Report.name,ReportData.flag,ReportData.path, 
     row_number() over(partition by ReportData.report_id order by flag) as rownum 
FROM Report 
JOIN ReportData on Report.id = ReportData.report_id 
) tmp 
WHERE tmp.rownum=1 
0

Eine einfachere Alternative zum LEFT JOIN, Rowid und rownum

SELECT id, name, flag, path 
FROM report, reportdata 
WHERE reportdata.rowid = (SELECT rowid 
          FROM reportdata 
          WHERE id = report_id 
          AND rownum = 1); 
0

Ohne Verwendung row_numner() verwenden Sie dies erreichen können.

Werfen Sie einen Blick auf diese SQL Fiddle

select r.id, r.name, d.flag, d.path from report r 
inner join reportdata d 
on r.id = d.report_id group by d.report_id 

PS: ich das Ergebnis war nicht zu glauben - ich war die Abfrage nur Gebäude - nicht d.report_id im select clause und es funktionierte verwendet. Wird die Aktualisierung dieser Antwort, sobald ich den Grund bekommen, warum diese Abfrage :)

0

Verwenden Partition BY gearbeitet:

declare @Report AS table 
(
    id int, 
    name varchar(10) 
) 

declare @ReportData AS table 
(
    report_id int , 
    flag bit, 
    path varchar(50) 
) 

insert into @Report values (1, 'a'); 
insert into @Report values (2, 'b'); 
insert into @Report values (3, 'c'); 

insert into @ReportData values (1, 0, 'xx'); 
insert into @ReportData values (2, 0, 'yy'); 
insert into @ReportData values (2, 1, 'yy'); 
insert into @ReportData values (3, 1, 'zz'); 
insert into @ReportData values (3, 1, 'mm'); 

;WITH T AS 
(
    Select 
     R.id, 
     r.name, 
     RD.flag, 
     RD.path, 
     ROW_NUMBER() OVER(PARTITION BY R.id ORDER BY R.id) AS PartNo 
    FROM @Report R 
    LEFT JOIN @ReportData RD ON R.id=RD.report_id 
) 
SELECT 
    T.id, 
    T.name, 
    T.flag, 
    T.path 
FROM T WHERE T.PartNo=1 
Verwandte Themen