合并多个表中的值

时间:2012-09-26 21:20:58

标签: asp.net sql linq join

我有一个应用程序,其数据分布在2个表格中。

有一个主表Main,它有列 - Id,Name,Type。 现在有一个Sub Main表,其中包含列 - MainId(FK),StartDate,Enddate,city 这是一对多的关系(每个main可以在子域中有多个条目)。

现在我要显示列Main.Id,City(从子域中为该主项的各行分隔的逗号),开始日期的min(来自该主项的子域)和enddate的最大值(来自sub main)

我想过有一个功能,但这会减慢速度,因为会有100k记录。还有其他方法可以做到这一点。顺便说一下应用程序是在asp.net中。我们可以有一个SQL查询或一些linq类的东西吗?

3 个答案:

答案 0 :(得分:1)

这是我的头脑,但首先我建议你在sql中创建一个用户定义的函数来创建接受@mainid的城市逗号分隔列表字符串,然后执行以下操作:

DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr+',' , '') + city
FROM submain
WHERE mainid = @mainid

...然后返回@listStr,它现在是一个以逗号分隔的城市列表。假设您调用函数MainIDCityStringGet()

然后,为了您的最终结果,您只需执行以下

即可
select cts.mainid,
       cts.cities,
       sts.minstartdate,
       sts.maxenddate
  from ( select distinct mainid,
                         dbo.MainIDCityStringGet(mainid) as 'cities'
           from submain) as cts
         join
       ( select mainid,
                min(startdate) as 'minstartdate',
                max(enddate)   as 'maxenddate'
           from submain
          group by mainid ) as sts on sts.mainid = cts.mainid
 where startdate <is what you want it to be>
   and enddate   <is what you want it to be>

根据您希望按startdate和enddate过滤的具体程度,您可能需要将where过滤器放在每个子查询中,然后在连接中的第二个子查询中,您可能需要使用HAVING分组过滤器。您没有明确说明过滤器的性质。

我希望有所帮助。

这当然是在存储过程中。可能需要一些调试。

答案 1 :(得分:0)

创建存储过程的替代方法是在客户端执行复杂操作。 (另):

var result = (from main in context.Main
              join sub in context.SubMain on main.Id equals sub.MainId into subs
              let StartDate = subs.Min(s => s.StartDate)
              let EndDate = subs.Max(s => s.EndDate)
              let Cities = subs.Select(s => s.City).Distinct()
              select new { main.Id, main.Name, main.Type, StartDate, EndDate, Cities })
             .ToList()
             .Select(x => new
                          {
                              x.Id,
                              x.Name,
                              x.Type,
                              x.StartDate,
                              x.EndDate,
                              Cities = string.Join(", ", x.Cities.ToArray())
                          })
             .ToList();

答案 2 :(得分:0)

我不确定在SQL的其他实施中如何支持它,但是如果你有SQL Server,这对这种情况起作用。

作为免责声明,我想补充一点,我不是这种技术的创始人。但是当我遇到它时,我立即想到了这个问题。

示例:

表格

Item ID       Item Value       Item Text
-----------  ----------------- ---------------
1             2                 A 
1             2                 B
1             6                 C
2             2                 D
2             4                 A
3             7                 B
3             1                 D

如果您想要以下输出,请将字符串连接起来并将值相加。

Item ID      Item Value        Item Text
-----------  ----------------- ---------------
1            10                 A, B, C 
2            6                  D, A
3            8                  B, D

以下内容避免了多语句循环解决方案:

if object_id('Items') is not null
  drop table Items
go

create table Items
     ( ItemId    int identity(1,1),
       ItemNo    int not null,
       ItemValue int not null,
       ItemDesc  nvarchar(500) )

insert Items
     ( ItemNo,
       ItemValue,
       ItemDesc )
values ( 1, 2, 'A'),
       ( 1, 2, 'B'),
       ( 1, 6, 'C'),
       ( 2, 2, 'D'),
       ( 2, 4, 'A'),
       ( 3, 7, 'B'),
       ( 3, 1, 'D')

select it1.ItemNo,
       sum(it1.ItemValue) as ItemValues,
       stuff((select ', ' + it2.ItemDesc  --// Stuff is just used to remove the first 2 characters, instead of a substring.
                from Items it2 with (nolock)
               where it1.ItemNo = it2.ItemNo
                 for xml path(''), type).value('.','varchar(max)'), 1, 2, '') as ItemDescs --// Does the actual concatenation..  
  from Items it1 with (nolock)
 group by it1.ItemNo

所以你看到你需要的只是你的select中的一个子查询,它检索你需要连接的所有值的一组,然后以聪明的方式在该子查询中使用FOR XML PATH命令。您需要连接的值来自哪里,只需要使用子查询检索它们无关紧要。