SQL - 多个查询或一个连接

时间:2014-01-22 18:20:28

标签: sql join

这里说的是我的数据库结构

TableA
{
    [ID] INT IDENTITY (1, 1) primary key,
    [Title] varchar (50) NOT NULL,
    [Details] varchar(50) NOT NULL
}

TableB:
{
    [ID] INT foreign key references [TableA] ([ID])
    [AvailableTime] DATETIME NOT NULL
}

TableC:
{
[ID] INT foreign key references [TableA] ([ID])
[AvailableLocation] varchar(50) NOT NULL
}

我需要表A中的所有列以及表B中针对特定ID的可用时间列表

结果应如下所示:新对象(id,title,details,List availableTime);

一个ID可能有多个可用时间。如果我执行两个单独的查询来检索这些信息或进行连接,然后通过列表循环两次,那么性能和速度方面会更好。 I.E.

select * from TableA where ID = 1;
select * from TableB where ID = 1;
select * from TableC where ID = 1;

...

OR

select * from TableA inner join TableB on TableA.ID = TableB.ID inner join TableC on TableA.ID = TableC.ID where ID = 1
List<DateTime> availableTime = new List<DateTime>();
foreach(DataRow row in resultTable.Rows)
{
    if (!availableTime.Contains((DateTime) row["AvailableTime"]))
        availableTime.Add((DateTime) row["AvailableTime"]);
}

foreach(DataRow row in resultTable.Rows)
{
    if (!availableLocation.Contains((string) row["AvailableTime"]))
        availableLocation.Add((string) row["AvailableLocation"]);
}
return new object ( id, resultTable.Rows[1], resultTable.Rows[2], availableTime,  availableLocation);

我在服务器(ASP.NET)上执行此操作,服务器负责在发送给用户之前运行查询和处理数据。

提前致谢。

3 个答案:

答案 0 :(得分:0)

如果我理解正确,您根本不需要join

select PropertyA
from tableA
where id = XXX
union all
select PropertyC
from tableB
where id = XXX;

如果您想删除重复项,请将union all更改为union

答案 1 :(得分:0)

简单连接查询将是这样的

Select A.*, B.AvailableTime 
from TableA A 
inner join TableB B on A.ID=B.ID

但是你可以通过使用连接到单个逗号单独的字符串

来避免重复
select A.*, ( SELECT ', ' + B.AvailableTime 
       FROM TableB B
       WHERE A.ID=B.ID 
       FOR XML PATH('') ) AS Timings
from TableA A 

但是,这取决于你的要求哪一个更适合你。

答案 2 :(得分:0)

在任何一种情况下,您都需要在客户端上进行处理才能从SQL中获取“树”。 SQL返回表格数据,这些数据被去规范化。


  

性能明智且速度明智,如果我执行两个单独的查询来检索这些信息或进行连接然后在列表中循环两次会更好吗?

通常,在SQL中进行连接更快更容易。在代码中手动循环SQL选择是有效地使RA无用的一种方法,因为任何散列/合并连接都变成“嵌套循环”。

由于C#通过LINQ支持这种转换,所以这是我的“第一选择” - 首先是在使用真正的LINQ-to-Database提供程序之后 - 来处理这种情况。

进行查询(我将其重命名为“id”以获得理智):

SELECT i.item_id, i.title, i.details, t.available_time
FROM items i 
JOIN times t ON t.item_id = i.item_id

“已加入”表单将返回(item_id, title, details, available_time)的结果集。

现在将查询结果读入“readItems”集合,使类型符合IEnumerable<{of the same fields as above}>,然后从数据重建树结构。

var items = readItems
    // The group by "re-normalize" on the key and the selector
    // is still key on RS - as the title/details are FDs on item_id
    .GroupBy(i => new { i.item_id, i.title, i.details })
    .Select(g => new ItemWithTimes {
        ItemId = g.Key.item_id,
        Title = g.Key.title,
        Details = g.Key.details,
        // capture collected data
        AvailableTimes = g,
    });

当然,如果您正在使用LINQ-to-SQL / EF提供程序(而不是上面想象的LINQ-to-Objects),那么您可以跳过手动浏览平面“readItems”结果集。


有一些例外,通常使用超反规范化结果集,其中多个查询可能更合适 - 这通常会影响真正深树或“大” “列是重复的。

此外,某些数据库(如SQL Server)支持XML,它可以处理超反规范化的结果集(也称为树),而无需通过平面表格结果集。

在任何情况下,您都知道在时机成熟时需要这样做 - 并且保持干净的DAL(而不是在整个地方泄漏访问权限)将使更改实现变得相对微不足道。