左外连接中的左侧是否可能只重复一次

时间:2015-04-08 13:27:38

标签: mysql sql-server optimization h2 outer-join

我有一个场景。不确定它是否完全可以通过简单的SQL查询。

表1

create table table1 (rowno int,
                     fileid int,
                     filename varchar(50),
                     filedata varchar(50),
                     valid boolean
                     );

insert into table1 (RowNo , FileId , FileName , fileData , Valid) values
(1, 1, 'FileA', 'blah blah..', true),
(2, 1, 'FileA', 'blah blah..', true),
(3, 1, 'FileA', 'blah blah..', true),
(4, 1, 'FileA', 'blah blah..', true),
(1, 2, 'FileB', 'blah blah..', false),
(2, 2, 'FileB', 'blah blah..', true),
(3, 2, 'FileB', 'blah blah..', false);

上面将给出如下表格 -

RowNo | FileId | FileName | Data        | Valid
1     |1       | FileA    | blah blah.. | TRUE 
2     |1       | FileA    | blah blah.. | TRUE 
3     |1       | FileA    | blah blah.. | TRUE 
4     |1       | FileA    | blah blah.. | TRUE 
1     |2       | FileB    | blah blah.. | FALSE 
2     |2       | FileB    | blah blah.. | TRUE 
3     |2       | FileB    | blah blah.. | FALSE 

表2

create table table2 (fileid int,
                     rowno int,
                     errormsg varchar(100)
                    );
insert into table2 (fileid , rowno , errormsg ) values (2,1,'manatory field is blank');
insert into table2 (fileid , rowno , errormsg ) values (2,3,'date format is wrong');

上面将给出如下表格 -

FILEID  |ROWNO   |ERRORMSG   
2       |1       |manatory field is blank 
2       |3       |date format is wrong 

如果我使用以下查询加入上表, -

select distinct t1.FILENAME,tot.TOTALREC, VALIDREC,coalesce((tot.TOTALREC- VALIDREC),0)INVALIDREC, t2.Rowno , case when coalesce((tot.TOTALREC- VALIDREC),0)=0 then null else t1.filedata end as ErrorData , t2.errormsg as ErrorMessage
from table1 t1
join (select count(*) totalrec, fileid from table1 group by fileid)tot on t1.fileid=tot.fileid
join (select count(*) VALIDREC , fileid from table1 where valid=true group by fileid)valid on t1.fileid=valid.fileid
left outer join table2 t2 on t1.fileid=t2.fileid 
order by t1.FILENAME;

我得到以下结果, -

实际结果

FILENAME | TOTALREC | VALIDREC | INVALIDREC | ROWNO | ERRORDATA | ERRORMESSAGE   
FileA    |   4      |    4     |     0      | null  | null      | null 
FileB    |   3      |    1     |     2      | 1     |blah blah..| manatory field is blank 
FileB    |   3      |    1     |     2      | 3     |blah blah..| date format is wrong 

但我需要一个结果集如下。

预期结果

FILENAME |TOTALREC|VALIDREC|INVALIDREC|ROWNO| ERRORDATA | ERRORMESSAGE   
FileA    |   4    |    4   |    0     | null| null      | null 
FileB    |   3    |    1   |    2     | 1   |blah blah..| manatory field is blank 
         |        |        |          | 3   |blah blah..| date format is wrong 

(注意最后一行的前四列。)

如果可以,有人可以帮我查询吗?

已更新: 为了澄清我的要求,正如您所要求的那样。

4 个答案:

答案 0 :(得分:1)

据我了解,如果某些字段与上一行中的相应字段相同,您是否希望将这些字段留空?

在MySQL中没有办法直接这样做。你最好用应用程序语言(PHP,VB,Java等)来做这件事。

可以使用@variables,IF()函数调用和ORDER BY来完成它。

答案 1 :(得分:0)

无法查看您在那里使用过的SQL,但如果您有类似的话,那么这是一般规则:

CASE WHEN RANK() OVER (PARTITIION BY a.filename ORDER BY a.rowno DESC) = 1 THEN <insert column here> END

它会过滤掉重复项,这取决于每个文件中的第一行等。

在SQL Server中,这确实提供了一种将掩码应用于某些记录而非其他记录的方法。

答案 2 :(得分:0)

COALESCE就是你想要的。

Select t.myfield, coalesce(t2.Myfield2, '') 
from mytable t
left join mytable2 t2 on t.mytableid = t2.mytableid

答案 3 :(得分:0)

首先,感谢大家的帮助。

@Rick - &gt;这是可能的。

我一直在寻找解决方案,现在特别针对H2数据库。但是,对于大多数支持排名的数据库或任何实现这一目标的数据库,解决方案都应该有效。我在此Stackoverflow link中找到了排名方法。

之后它是小菜一碟!!

以下是感兴趣的人的解决方案查询 -

select 
case when (final.INVALIDREC>0 and final.ranking>1) then '' else final.FileName end as FileName,
case when (final.INVALIDREC>0 and final.ranking>1) then '' else cast(final.TOTALREC as varchar(50)) end as TOTALREC,
case when (final.INVALIDREC>0 and final.ranking>1) then '' else cast(final.VALIDREC as varchar(50)) end as VALIDREC,
case when (final.INVALIDREC>0 and final.ranking>1) then '' else cast(final.INVALIDREC as varchar(50)) end as INVALIDREC, final.Rowno , final.ErrorData , final.ErrorMessage
from
(select 
   (
    select  count(*)
    from    (select distinct t1.FILENAME, t2.Rowno from table1 t1
    left outer join table2 t2 on t1.fileid=t2.fileid 
    order by t1.FILENAME) yt2
    where   yt2.FILENAME = temp.FILENAME -- Same partition
            and yt2.Rowno <= temp.Rowno -- Lower or equal rank
    ) as ranking,
temp.FILENAME,temp.TOTALREC, temp.VALIDREC,temp.INVALIDREC, temp.Rowno , temp.ErrorData , temp.ErrorMessage
from
(select distinct t1.FILENAME,tot.TOTALREC, VALIDREC,coalesce((tot.TOTALREC- VALIDREC),0)INVALIDREC, t2.Rowno , case when coalesce((tot.TOTALREC- VALIDREC),0)=0 then null else t1.filedata end as ErrorData , t2.errormsg as ErrorMessage
from table1 t1
join (select count(*) totalrec, fileid from table1 group by fileid)tot on t1.fileid=tot.fileid
join (select count(*) VALIDREC , fileid from table1 where valid=true group by fileid)valid on t1.fileid=valid.fileid
left outer join table2 t2 on t1.fileid=t2.fileid 
order by t1.FILENAME, t2.rowno) temp)final;

这将提供预期结果

*非常感谢..这是我在Stack Overflow中的第一篇文章,并且在获得如此多的帮助时感到谦虚..

快乐的编码!! *