新手SQL更新问题

时间:2011-06-25 17:41:54

标签: sql sql-server sql-server-2005 tsql

修改查询.. [Id]列对于所有记录都是唯一的..查询应该将CorEURUSD的正确值返回到Symbol = EURUSD和Symbol = GBPUSD,其中[Time] = [Time]值。

 CREATE TABLE [dbo].[Tck2](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Symbol] [varchar](35) NULL,
[Time] [datetime] NULL,
[CorEURUSD] [decimal](14, 10) NULL,
[CorEURUSD2] [decimal](14, 10) NULL
  ) ON [PRIMARY]


 INSERT [VT7STAB1].[dbo].[Tck2] ([Symbol],[Time],[CorEURUSD],[CorEURUSD2]) VALUES('EUR/USD', '2011-07-01 12:04:28.000', 0.8229, 0.6488)
 INSERT [VT7STAB1].[dbo].[Tck2] ([Symbol],[Time],[CorEURUSD],[CorEURUSD2]) VALUES('EUR/USD', '2011-07-01 12:26:17.000', 0.9427, 0.6558)
 INSERT [VT7STAB1].[dbo].[Tck2] ([Symbol],[Time],[CorEURUSD],[CorEURUSD2]) VALUES('EUR/USD', '2011-07-01 12:58:34.000', 0.7713, 0.5267)
 INSERT [VT7STAB1].[dbo].[Tck2] ([Symbol],[Time],[CorEURUSD],[CorEURUSD2]) VALUES('GBP/USD', '2011-07-01 12:04:28.000', 0, 0)
 INSERT [VT7STAB1].[dbo].[Tck2] ([Symbol],[Time],[CorEURUSD],[CorEURUSD2]) VALUES('GBP/USD', '2011-07-01 12:26:17.000', 0, 0)
 INSERT [VT7STAB1].[dbo].[Tck2] ([Symbol],[Time],[CorEURUSD],[CorEURUSD2]) VALUES('GBP/USD', '2011-07-01 12:58:34.000', 0, 0)

运行以下查询以尝试将符号 - 'EUR / USD'中的CorEURUSD列复制到符号='GBP / USD

的结果CorEURUSD列中
update Tck2
set CorEURUSD = (
     select CorEURUSD
     from Tck2 T 
     where Symbol = 'EUR/USD')
 where Symbol = 'GBP/USD'

发出此错误 消息512,级别16,状态1,行1 子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。 声明已经终止。

当我使用这个修订版时..

update Tck2
set CorEURUSD = (
     select CorEURUSD
     from Tck2 T 
     where Symbol = 'EUR/USD')
 where Symbol = 'GBP/USD'
 and T.[Time] = [Time]

它会抛出此错误。

Msg 4104,Level 16,State 1,Line 2 无法绑定多部分标识符“T.Time”。

我希望这更好,抱歉'群众混淆'请修改答案以匹配上述查询和表格,这应该是正确的。

5 个答案:

答案 0 :(得分:3)

错误消息是说您的子查询:

SELECT [CorEURUSD] 
  FROM TicksForex T 
 WHERE [Symbol] = 'EUR/USD' 
   AND T.[id] = [id]

...返回多个值。无法在单个列中存储多个值。您可以使用聚合来获取最高值:

SELECT MAX([CorEURUSD])
  FROM TicksForex T 
 WHERE [Symbol] = 'EUR/USD' 
   AND T.[id] = [id]

...或最低:

SELECT MIN([CorEURUSD])
  FROM TicksForex T 
 WHERE [Symbol] = 'EUR/USD' 
   AND T.[id] = [id]

...但您没有提供我们使用的详细信息。

答案 1 :(得分:3)

根据松散的规格和没有样本数据/期望的结果进行猜测。

UPDATE t
    SET t.[CorEURUSD] = x.[CorEURUSD] 
    FROM dbo.TicksForex AS t
    INNER JOIN dbo.TicksForex AS x
    ON t.[id] = x.[id]
    WHERE 
        t.[Symbol] = 'GBP/USD'
        AND x.[Symbol] = 'EUR/USD';

编辑2011-07-03 根据修订后的规格。 [时间]真的会成为此类更新的关键吗?听起来有风险。无论如何,因为[时间]是我根据你的叙述和样本数据确定加入两行的唯一方法,所以我认为你的意思(我也可以假设你只想更新CorEURUSD而不是CorEURUSD2): / p>

UPDATE t
    SET t.[CorEURUSD] = x.[CorEURUSD]
    FROM dbo.Tck2 AS t
    INNER JOIN dbo.Tck2 AS x
    ON t.[Time] = x.[Time]
    WHERE t.Symbol = 'GBP/USD'
    AND x.Symbol = 'EUR/USD';

真的没那么多修改,我只是改变了连接条件。

答案 2 :(得分:1)

三个问题:

  1. 缺少括号。
  2. T.[id] = [id]条件没有多大意义,因为它等同于id = id,这总是正确的。

    以下查询应该有效,假设Symbol是唯一的:

    update TicksForex 
    set [CorEURUSD] = (
            select CorEURUSD 
            from TicksForex 
            where Symbol = 'EUR/USD'
        )
    where Symbol = 'GBP/USD'
    
  3. 但是,根据您的错误提示Symbol并非唯一。

    解决此问题的可能方法:

    • 删除重复项。我相信这是最好的解决方案,但根据问题的信息
    • 无法确定
    • 取第一个值:

      update TicksForex 
      set CorEURUSD = (
          select top 1 CorEURUSD
          from TicksForex T 
          where Symbol = 'EUR/USD')
      where Symbol = 'GBP/USD'
      
    • 选择minmaxavg等值:

      update TicksForex 
      set CorEURUSD = (
          select max(CorEURUSD)
          from TicksForex T 
          where Symbol = 'EUR/USD')
      where Symbol = 'GBP/USD'
      

    基本上,您需要确保没有重复项,或者指定应将哪个完全重复的行用作CorEURUSD值的来源。


  4. 我测试的方式:

    1. 使用您的脚本创建表格。
    2. 填充表格有两行:

      insert TicksForex
      values('GBP/USD', 10, 20, 100)
      
      insert TicksForex
      values('EUR/USD', 30, 40, 200)
      
    3. 按原样运行查询:

      update TicksForex 
      set CorEURUSD = 
          select CorEURUSD
          from TicksForex T 
          where Symbol = 'EUR/USD' and T.[id] = [id]
      where Symbol = 'GBP/USD'
      

      错误:

      Msg 156, Level 15, State 1, Line 3
      Incorrect syntax near the keyword 'select'.
      Msg 156, Level 15, State 1, Line 6
      Incorrect syntax near the keyword 'where'.
      
    4. 添加了括号并删除了and T.[id] = [id]

      update TicksForex 
      set CorEURUSD = (
          select CorEURUSD
          from TicksForex T 
          where Symbol = 'EUR/USD')
      where Symbol = 'GBP/USD'
      

      的工作。

    5. 添加了重复的行:

      insert TicksForex
      values('EUR/USD', 50, 60, 300)
      
    6. 再次编写脚本:

      错误:

      Msg 512, Level 16, State 1, Line 1
      Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
      
    7. 从上面的回答中尝试了所有3个解决方案 - 工作。

    8. [编辑] 提供样本数据后。

      如果时间绝对匹配,您可以这样做:

      update t1 
      set CorEURUSD = t2.CorEURUSD, CorEURUSD2 = t2.CorEURUSD2
      from Tck2 t1 
          join Tck2 t2 on
              t1.Time = t2.Time
      where 
          t1.Symbol = 'GBP/USD' and
          t2.Symbol = 'EUR/USD' 
      

      如果时间不完全匹配,您可以这样做:

      ;with 
      cte1 as
      (
          select *, row_number() over (order by Time) RowNumber
          from Tck2
          where Symbol = 'EUR/USD'
      ),
      cte2 as
      (
          select *, row_number() over (order by Time) RowNumber
          from Tck2
          where Symbol = 'GBP/USD'
      )
      update cte2
      set CorEURUSD = cte1.CorEURUSD, CorEURUSD2 = cte1.CorEURUSD2
      from cte1 
          join cte2 on
              cte1.RowNumber = cte2.RowNumber
      

答案 3 :(得分:0)

首先,您需要在子查询周围使用括号,否则会抛出另一个错误:

UPDATE TicksForex 
   SET [CorEURUSD] = ( SELECT [CorEURUSD] 
                        FROM TicksForex T 
                       WHERE [Symbol] = 'EUR/USD' 
                     )
WHERE [Symbol] = 'GBP/USD' ;

其次,错误表明有多个行[Symbol] = 'EUR/USD'。 此查询将显示的数字超过1

SELECT COUNT(*) 
FROM [TicksForex] 
WHERE [Symbol] = 'EUR/USD' ;

答案 4 :(得分:0)

现在我得到了你的问题

这是您的查询:

update a
set a.[CorEURUSD] = b.[CorEURUSD]
from [dbo].[Tck2] as a
join [dbo].[Tck2] as b on a.[Time] = b.[Time]
where a.[Symbol] = 'GBP/USD' and b.[Symbol]= 'EUR/USD'