Naz*_*gul 20 sql sql-server sql-server-2005 linq-to-sql
我正在构建一个动态生成sql的应用程序来搜索特定表的行(这是主域类,如Employee).
Table1,Table2和Table1Table2Map有三个表.Table1与Table2有多对多的关系,并通过Table1Table2Map表进行映射.但由于Table1是我的主要表格,因此这种关系几乎就像一对一.
我的应用程序生成一个sql,它基本上给出了一个包含所有这些表中的行的结果集.select子句和连接不会更改,而where子句是基于用户交互生成的.在任何情况下,我都不希望在我的结果集中重复使用Table1,因为它是结果显示的主表.现在,生成的查询是这样的:
select distinct Table1.Id as Id, Table1.Name, Table2.Description from Table1
left outer join Table1Table2Map on (Table1Table2Map.Table1Id = Table1.Id)
left outer join Table2 on (Table2.Id = Table1Table2Map.Table2Id)
Run Code Online (Sandbox Code Playgroud)
为简单起见,我排除了where子句.问题是Table2中Table1中有多行,即使我已经说明了Table1的不同.Id结果集有重复的Table1行,因为它必须选择Table2中的所有匹配行.
为了详细说明,请考虑对于Table1中Id = 1的行,Table1Table2Map(1,1)和(1,2)中有两行将Table1映射到Table2中的两行,其中ID为1,2.上述查询返回这种情况下重复的行.现在我希望查询只返回Id 1一次的Table1行.这是因为Table2中只有一行类似于Table1中相应条目的活动值(此信息在Mapping表中).有没有办法可以避免获取Table1的重复行.
我认为我试图解决问题的方式存在一些基本问题,但我无法弄清楚它是什么.提前致谢.
ang*_*son 25
尝试:
left outer join (select distinct YOUR_COLUMNS_HERE ...) SUBQUERY_ALIAS on ...
Run Code Online (Sandbox Code Playgroud)
换句话说,不要直接加入表,加入一个限制你加入的行的子查询.
kom*_*mer 12
你可以使用 GROUP BY on Table1.Id,这将摆脱额外的行.你不需要担心加入方面的任何机制.
我在一个巨大的查询中提出了这个解决方案,而且这个解决方案并没有太多影响查询时间.
注意:我在被问到3年后回答这个问题,但这可能对我相信的人有所帮助.
您可以将左连接重写为外部适用,以便您可以按如下方式使用前1和顺序:
select Table1.Id as Id, Table1.Name, Table2.Description
from Table1
outer apply (
select top 1 *
from Table1Table2Map
where (Table1Table2Map.Table1Id = Table1.Id) and Table1Table2Map.IsActive = 1
order by somethingCol
) t1t2
outer apply (
select top 1 *
from Table2
where (Table2.Id = Table1Table2Map.Table2Id)
) t2;
Run Code Online (Sandbox Code Playgroud)
请注意,没有"top"或"order by"的外部应用完全等同于左外部连接,它只是为您提供更多控制.(交叉申请相当于内部联接).
你也可以使用row_number()函数做类似的事情:
select * from (
select distinct Table1.Id as Id, Table1.Name, Table2.Description,
rowNum = row_number() over ( partition by table1.id order by something )
from Table1
left outer join Table1Table2Map on (Table1Table2Map.Table1Id = Table1.Id)
left outer join Table2 on (Table2.Id = Table1Table2Map.Table2Id)
) x
where rowNum = 1;
Run Code Online (Sandbox Code Playgroud)
如果IsActive标志可以将您的其他表缩小到一行,则大多数情况不适用,但它们可能会对您有用.
| 归档时间: |
|
| 查看次数: |
79283 次 |
| 最近记录: |