左连接中基于行的条件

时间:2016-09-19 12:16:52

标签: sql-server

有没有办法在Left Join中写一个基于行的条件。

如果根据列条件不存在某行,则应该采用下一个第一行。

我有以下结构,

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');

我需要一些像

这样的输出
1 a 0 xx
2 b 0 yy
3 c 1 zz

5 个答案:

答案 0 :(得分:1)

您可以使用ROW_NUMBER

;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

上述查询视为每个report_id切片的第一个记录,字母最小 path。您可以根据需要修改ORDER BY窗口函数的ROW_NUMBER()子句。

答案 1 :(得分: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

答案 2 :(得分:0)

使用rowid和rownum

的左连接的简单替代方法
SELECT id, name, flag, path
FROM   report, reportdata 
WHERE  reportdata.rowid = (SELECT rowid 
                           FROM   reportdata 
                           WHERE  id = report_id 
                           AND    rownum = 1);

答案 3 :(得分:0)

不使用row_numner()就可以实现这一目标。

看一下 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:我不相信结果 - 我只是在构建查询 - 未在d.report_id中使用select clause并且它有效。一旦得到此查询有效的原因,将更新此答案:)

答案 4 :(得分:0)

使用 Partition BY

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