【问题标题】:INSERT INTO two columns from a SELECT query从 SELECT 查询中插入两列
【发布时间】:2021-06-28 14:11:33
【问题描述】:

我有一个名为 VIEWS 的表格,其中包含 ID、日期、月份、视频名称、浏览器名称...但我只对 ID、日期和月份感兴趣。

ID 可以重复,因为用户 (ID) 可以在多个月内多天观看视频。

这是最小日期和最大日期的查询。

SELECT ID, CONCAT(MIN(DAY), '/', MIN(MONTH)) AS MIN_DATE, 
CONCAT(MAX(DAY), '/', MAX(MONTH)) AS MAX_DATE, 
FROM Views
GROUP BY ID

我想将此包含两列(MIN_DATE 和 MAX_DATE)的选择插入到两个新列中并插入。

如何插入查询?

【问题讨论】:

  • 请提供样本数据和期望的结果。
  • 请不要标记多个 RDBMS。 [sql-server] 和 [postgresql] 是完全不同的产品。
  • 是否要在新表中插入。

标签: sql sql-server


【解决方案1】:

要执行您正在尝试执行的操作(您的解决方案存在一些问题,请阅读下面的我的 cmets),首先您需要将新列添加到表中。

ALTER TABLE Views ADD MIN_DATE VARCHAR(10)
ALTER TABLE Views ADD MAX_DATE VARCHAR(10)

然后你需要UPDATE你的新列(不是INSERT,因为你不想要新行)。确定每个ID 的最小值/最大值,然后将结果连接回表以便能够更新每一行。您无法直接从 GROUP BY 更新,因为行已分组并丢失其原始行。

;WITH MinMax 
(
    SELECT 
        ID, 
        CONCAT(MIN(V.DAY), '/', MIN(V.MONTH)) AS MIN_DATE, 
        CONCAT(MAX(V.DAY), '/', MAX(V.MONTH)) AS MAX_DATE 
    FROM 
        Views AS V
    GROUP BY
        ID
)
UPDATE V SET
    MIN_DATE = M.MIN_DATE,
    MAX_DATE = M.MAX_DATE
FROM
    MinMax AS M
    INNER JOIN Views AS V ON M.ID = V.ID

我在这个设计中看到的问题是:

  • 存储聚合列:您通常只想为性能问题执行此操作(我认为这里不是这种情况),因为查询聚合(分组)行会更快,因为行数较少读书。问题是每次更新原始行之一时,您都必须更新分组值,这是额外的处理时间。另一种选择是定期更新聚合值,但您必须接受在一段时间内,分组值并不能真正代表跟踪表。

  • 将聚合列与它们正在聚合的数据保持在同一个表中:这是规范化问题。更新或插入行将触发更新具有相同 ID 的所有行,因为最小值/最大值可能已更改。此外,最小/最大值将始终在属于同一 ID 的所有行上重复,这是您浪费的额外空间。如果必须保存聚合数据,则需要将其保存在不同的表中,这会导致我在上一点列出的问题。

  • 使用文本数据类型存储日期:您总是希望使用正确的 DATETIME 数据类型来处理日期。这不仅可以使用DATEADDDATEDIFF 等日期函数,还可以节省空间(存储日期的varchars 需要比DATETIME 更多的字节)。我没有在您的查询中看到年份部分,应该考虑计算最小值/最大值(这可能取决于您在此表上存储的内容)。

  • 计算最小值/最大值不正确:如果您有以下行:

     ID  DAY MONTH
     1   5   1
     1   3   2
    

    您查询的当前结果将是3/1 作为MIN_DATE5/2 作为MAX_DATE,我相信这不是您想要找到的。这里最低的应该是 1 月 5 日,最高的应该是 2 月 3 日。这是将日期部分存储为独立值而不是将整个日期存储为 DATETIME 的结果。

对于这种情况,您通常想要做的是直接对需要分组数据的查询进行分组,因此您将对需要最小/最大值的SELECT 执行GROUP BY。拥有ID 的索引将使分组非常快。因此,您节省了用于保存聚合值的存储空间,而且结果始终是您查询时的真实分组结果。

应该是这样的:

;WITH MinMax 
(
    SELECT 
        ID, 
        CONCAT(MIN(V.DAY), '/', MIN(V.MONTH)) AS MIN_DATE, -- Date problem (varchar + min/max computed seperately)
        CONCAT(MAX(V.DAY), '/', MAX(V.MONTH)) AS MAX_DATE -- Date problem (varchar + min/max computed seperately)
    FROM 
        Views AS V
    GROUP BY
        ID
)
SELECT
    V.*,
    M.MIN_DATE,
    M.MAX_DATE
FROM
    MinMax AS M
    INNER JOIN Views AS V ON M.ID = V.ID

【讨论】:

  • 谢谢EzLo,多么棒的详细回复!在这种情况下,我对更新查询有疑问。我在第一个 SELECT“期望 ID 或 QUOTED_ID”中出现错误,然后在关闭此 SELECT 的“)”中出现错误。而且我在 UPDATE 中有一些错误,也许这不适合 SQLServer?
  • MAX_DATE 别名后多了一个逗号。立即尝试。
猜你喜欢
  • 1970-01-01
  • 2012-07-11
  • 2012-07-23
  • 2021-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-26
  • 1970-01-01
相关资源
最近更新 更多