从SELECT查询中插入两列



我有一个名为VIEWS的表,其中包含Id、Day、Month、视频名称、浏览器名称。。。但我只对Id、Day和Month感兴趣。

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(的select插入到带有insert的两个新列中。

如何将插入到查询中?

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

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相同的所有行。此外,min/max值将始终在属于同一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

最新更新