【问题标题】:Selecting rows from other tables based on the first table using SQL使用 SQL 根据第一个表从其他表中选择行
【发布时间】:2019-01-17 00:27:33
【问题描述】:

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

SELECT * FROM Clients

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

SELECT * FROM History

第二个,从历史表中选择所有历史条目。然后我使用一些代码来查找每个客户端的第一个历史记录。即ClientID 表中的第一个历史记录被设置到ClientIDHasHistory 列中。

SELECT * FROM Actions

最后一个,我从动作表中得到所有动作。然后我使用一些代码来查找每个客户端的最后一个操作。即 ClientID 表中的最后一个操作被设置到 ClientIDLastAction 列中。

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

SELECT * 
FROM Clients

AND 

SELECT First History Row 
FROM History 
WHERE History.ClientID = Clients.ClientID

AND 

SELECT Last Action Row 
FROM Actions 
WHERE Actions.ClientID = Clients.ClientID

【问题讨论】:

  • 提示:INNER JOINUNIONTOP 1 取决于您的目标
  • TOP 1 是否获得第一行?对不起,如果这是一个愚蠢的问题。我对 SQL 的经验很少,所以不知道 INNER JOIN、UNION 或 TOP 1 是什么意思。
  • 刚刚查找了UNION,但我认为这不会起作用。 w3schools.com/sql/sql_union.asp
  • 您应该首先了解INNER JOIN,它是SQL 的一个基本组件。然后,您需要在 HistoryActions 表中找到一个列,该列指示“最后”记录是什么。此表中是否有日期或数字列表明这一点?
  • 要回答你需要向我们展示每个表的所有列以及预期结果是什么

标签: sql .net sql-server


【解决方案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

这就是说:获取客户端(我们将其称为 C),然后对于每一行,尝试加入(匹配来自的行)我们在上面查看的历史查询(我们将其称为 H)其中客户端 ID 相同且 orderNo 为 1 - 即第一个历史记录行。它也对 Actions 查询执行相同的操作。

【讨论】:

    猜你喜欢
    • 2018-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-19
    • 1970-01-01
    • 2019-12-13
    • 2010-12-21
    • 2018-05-02
    相关资源
    最近更新 更多