【问题标题】:Consolidating values from multiple tables合并来自多个表的值
【发布时间】:2012-09-26 21:20:58
【问题描述】:

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

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

现在我想显示列 Main.Id、City(作为逗号与子主项的该主项的各个行分隔)、开始日期的最小值(该主项的子项)和结束日期的最大值(子主项) .

我想有一个函数,但因为会有 10 万条记录,所以这会减慢速度。有没有其他方法可以做到这一点。顺便说一句,该应用程序位于 asp.net 中。我们可以有一个 sql 查询或一些 linq 之类的东西吗?

【问题讨论】:

  • 我忘了提...我还需要使用开始和结束日期进行过滤。
  • Google 'sql SELECT LEFT JOIN WHERE'
  • 你在使用实体框架吗?
  • 不,我没有使用实体框架。

标签: asp.net sql linq join


【解决方案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 分组过滤器。您没有明确说明过滤器的性质。

希望对你有帮助。

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

【讨论】:

  • 谢谢阿诺。如果有十万条记录,功能会变慢吗? ...最终我还将加入另外 4 个表。
  • 请原谅迟到的回复。我不得不打干草。该函数无疑会产生性能成本,因为从表中构建逗号分隔的字符串会产生成本。
【解决方案2】:

创建存储过程的另一种方法是在客户端执行复杂的操作。 (未经测试):

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

【讨论】:

    【解决方案3】:

    我不确定在其他 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
    

    所以你看到你所需要的只是你的选择中的一个子查询,它检索一组你需要连接的所有值,然后以一种聪明的方式在该子查询中使用 FOR XML PATH 命令。您需要连接的值来自哪里并不重要,您只需使用子查询检索它们即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-29
      • 2018-02-26
      • 2021-12-09
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 2018-09-11
      • 1970-01-01
      相关资源
      最近更新 更多