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 查询 - 复制同一表中的值的主要内容,如果未能解决你的问题,请参考以下文章