SQL 查询 - 复制同一表中的值

Posted

技术标签:

【中文标题】SQL 查询 - 复制同一表中的值【英文标题】:SQL Query - Copy Values in Same Table 【发布时间】:2009-09-09 14:55:41 【问题描述】:

所以我有一个看起来像这样的表:

项目 ID 任务 ID 日期 000 001 2009 年 10 月 28 日 000 002 09 年 12 月 1 日 000 003 02/24/10 001 001 04/14/10 001 002 07/5/10 001 003 2011 年 2 月 24 日 002 001 06/07/10 002 002 07/7/10 002 003 2012 年 9 月 13 日

假设有许多项目和许多任务,但每个项目都包含相同的任务。我想按以下方式复制日期:

一个项目 (000) 具有主日期。我想将每个任务的这些日期复制到其他几个项目(示例数据中的 001、002)。

因此,如果项目 000 中的任务 001 的日期为 10/28/09,我希望其他项目中的任务 001(我知道他们的 ID)具有相同的日期。

如果项目 001 中的任务 002 的日期为 12/1/09,我希望任务 002 在其他每个项目中也有此日期。

有没有一个查询可以做到这一点?我认为应该有,但我现在想不通。

顺便说一句,我使用的是 SqlServer 2005。

【问题讨论】:

【参考方案1】:
UPDATE dbo.Projects
SET Date = (SELECT Date FROM dbo.Projects p1
            WHERE p1.ProjectID = '000' AND p1.TaskID = dbo.Projects.TaskID)
WHERE ProjectID IN ('P01', 'P02', 'P03', 'P04')
AND TaskID IN ('001', '002', '003')

这对你有用吗?

所以对于TaskID = 001,这条语句会

 SELECT Date FROM dbo.Projects WHERE ProjectID = '000' AND TaskID = '001'

然后将每个项目 (P01-P04) 和 TaskID=001 更新到此日期。这就是你要找的东西,不是吗?

您还可以使用 OUTPUT 子句向您证明正在更新的内容:

UPDATE dbo.Projects
SET Date = (SELECT Date FROM dbo.Projects p1
            WHERE p1.ProjectID = '000' AND p1.TaskID = dbo.Projects.TaskID)
OUTPUT inserted.ProjectID, inserted.TaskID, inserted.Date
WHERE ProjectID IN ('P01', 'P02', 'P03', 'P04')
AND TaskID IN ('001', '002', '003')

这将导致更新每一行以输出新值(例如更新后),因此您可以检查并查看更新的内容以及更新的值。

刚刚运行查询,这是我得到的结果:

ProjectID   TaskID  Date
   0       1    2009-10-28 00:00:00.000
   0       2    2009-12-01 00:00:00.000
   0       3    2010-02-24 00:00:00.000
   1       1    2009-10-28 00:00:00.000
   1       2    2009-12-01 00:00:00.000
   1       3    2010-02-24 00:00:00.000
   2       1    2009-10-28 00:00:00.000
   2       2    2009-12-01 00:00:00.000
   2       3    2010-02-24 00:00:00.000

项目 1 和 2 以及任务 1、2、3 的日期已设置为“主”项目 0 的值。

【讨论】:

乍一看,这个查询似乎并不匹配每个任务的从主人到其他人的日期。我读错了吗? 它为您正在处理的每个 TaskID 从项目“000”中选择“日期”,并将其他项目的“日期”设置为该选定日期 投票给你的人是在抽烟,这很有效并且有很好的解释。非常感谢! 您被否决了,因为在 SET 列表中执行额外的 SELECT 会导致不必要的标量计算和执行计划中的***步骤,而使用 JOIN 不会。 @CptSkippy:感谢您解释您的动机。好的,同意 - 这不是绝对必要的,可以通过其他方式完成。然而,在这个规模上——三个项目和三个任务——我怀疑它是否真的会产生可衡量的差异.....【参考方案2】:

大概是这样的:

INSERT INTO Projects(ProjectID, TaskID, Date)
SELECT P2.ProjectId, P1.TaskID, P1.Date
FROM Projects P1
CROSS JOIN (SELECT DISTINCT ProjectID FROM Projects WHERE ProjectId <> '000') P2

我不确定您使用的是哪个数据库引擎,有些可能允许比上述更自然的语法。

以上显然还假设尚未为其他项目设置时间段,并且您正在尝试定义新的时间段而不是更新现有的时间段。

【讨论】:

【参考方案3】:

这应该可以正常工作:

UPDATE projects SET [date] = (SELECT [date] FROM projects p1 WHERE project = '000' AND p1.task = projects.task)

【讨论】:

【参考方案4】:

这是您想要的,只需将“...”替换为 CSV 项目列表即可。

UPDATE c
SET c.Date = p.Date
FROM Projects AS [c]
JOIN Projects AS [p]
    ON p.TaskID = c.TaskID
    AND p.ProjectID = '000'
WHERE c.ProjectID IN (...)

【讨论】:

【参考方案5】:
DECLARE @MasterProjectId varchar(10)
DECLARE @ChildProjectIds varchar(100)

Select 
@MasterProjectId = '000',
@ChildProjectIds = '''123'',''456'''


EXECUTE sp_executesql N'Update childProjects
Set childProjects.[Date]= masterProject.[Date]
from Projects masterProject
Inner join Projects childProjects on childProjects.TaskId = masterProject.TaskId and childProjects.ProjectId in (' + @ChildProjectIds + ')
where masterProject.ProjectId = ' + @MasterProjectId

【讨论】:

真的没有必要创建动态 SQL 语句并执行它——看起来过于复杂,IMO 为了更好地格式化您的代码,您应该突出显示您的代码行,然后按工具栏上的“代码”按钮 (010 101) - 让世界变得与众不同!

以上是关于SQL 查询 - 复制同一表中的值的主要内容,如果未能解决你的问题,请参考以下文章

SQL语句把同一个表中的a字段中的数据复制到另一个字段b中

SQL克隆/复制同一表中的记录与条件

SQL语句把同一个表中的a字段中的数据复制到另一个字段b中

将数据复制到同一张表和从同一表复制数据,并将复制数据的一列中的值更改为指定值

SQL UPDATE(从一行复制到另一行)

Oracle:使用其他表中的值进行更新