使用SQL根据第一个表从其他表中选择行

时间:2019-01-17 00:27:34

标签: sql .net sql-server

我想将三个T-SQL语句合并为一个,因此它只是对数据库的一次调用,而不是三个。

SELECT * FROM Clients

第一个,从“客户”表中选择每个客户。

SELECT * FROM History

第二个,从“历史记录”表中选择所有历史记录条目。然后,我使用一些代码来查找每个客户端的第一个历史记录。也就是说,ClientID表中的第一个历史记录已设置为该HasHistory的{​​{1}}列中。

ClientID

最后一个,我从动作表中获取所有动作。然后,我使用一些代码为每个客户端找到最后一个动作。也就是说,SELECT * FROM Actions 表中的最后一项操作已设置到该ClientID的{​​{1}}列中。

所以我想知道是否有一种方法可以编写这样的SQL语句?请注意,这不是真正的SQL,只是伪代码来说明我要实现的目标。

LastAction

1 个答案:

答案 0 :(得分:0)

您可以通过多种方法来执行此操作,但这是一个示例。我将一次处理它,以解释我们在做什么。您尚未向我们展示表设计,所以列名是一个猜测,但您应该有所了解。

首先,您必须以某种方式标记您关心的历史记录行。一种方法是执行查询,在每个历史记录行上放置一个订单号,每个新客户从1开始,并按日期对其进行排序。这样,每个客户端(所需的客户端)的第一历史记录行的行号始终为1。看起来像

SELECT
    *, 
    ROW_NUMBER() OVER (PARTITION BY clientID ORDER BY historyDate) AS orderNo 
FROM
    History

除了要执行最新操作(而不是第一个操作)外,您将执行与操作类似的操作,因此按列排序必须是相反的顺序-您可以通过告诉ORDER BY使用降序来执行此操作,例如这个

SELECT 
    *, 
    ROW_NUMBER() OVER (PARTITION BY clientID ORDER BY actionDate DESC) AS orderNo 
FROM Actions

您现在应该有两个查询,其中只将您想要的行标记为一个订单号。现在要做的是从第一个查询开始,然后加入其他两个查询,以便仅加入orderno = 1行。然后,您想要的所有数据将在一行中可用。您必须决定使用哪种连接类型-内部连接只会返回实际上具有历史记录和操作的客户端。如果要查看其他表中根本没有行的客户端,则需要使用左外部联接。但是您的最终查询(您只需要此查询)看起来就像

SELECT
    C.*, H.*, A.*
FROM
    Clients C
LEFT OUTER JOIN 
    (SELECT
         *, 
         ROW_NUMBER() OVER (PARTITION BY clientID ORDER BY historyDate) AS orderNo 
     FROM History) H ON H.clientID = C.clientID AND H.orderNo = 1
LEFT OUTER JOIN 
    (SELECT
         *, 
         ROW_NUMBER() OVER (PARTITION BY clientID ORDER BY actionDate DESC) AS orderNo 
     FROM Actions) A ON A.clientID = C.clientID AND A.orderNo = 1

这是说:拿Clients(我们称为C),然后对于每一行,尝试加入并与我们上面看过的History查询(称为H)匹配(匹配一行),其中客户ID相同且orderNo为1-即第一条历史记录行。动作查询也是如此。