【问题标题】:Set column value based on another column's value根据另一列的值设置列值
【发布时间】:2018-11-22 21:10:50
【问题描述】:

我有一个包含 4 列的表:

ItemId, ItemPrice, DateFrom, DateTo

该表包含有关商品、价格和价格变化日期的信息

例如:

我想要做的是填写 DateTo 列,以便我知道价格持续了多长时间以及是否仍然持续

我期望的结果:

还有一个重要的注意事项是价格变化的数量是未知的,对于某些项目它会更改 3 次,而对于某些项目则根本没有变化,并且价格直到今天都保持不变。

我们将不胜感激任何形式的帮助。

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    视图会是更好的解决方案,因为不需要AFTER UPDATE 触发器,并且您不能保留具有值GETDATE() 的列(因此您必须更新@ 的值987654323@ 在每一天的开始)。这将为您提供您想要的结果:

    CREATE VIEW YourView AS
    
        SELECT ItemId,
               ItemPrice,
               DateFrom,
               LEAD(DATEADD(DAY,-1,DateFrom),1,GETDATE()) OVER (PARTITION BY ItemId ORDER BY DateFrom ASC) AS DateTo
        FROM YourTable;
    

    【讨论】:

    • 这完全符合我的需要,非常感谢!
    • 不客气@mjohansen。如果是这样,请记住将答案标记为解决方案,以便其他有相同/相似问题的人知道它对您有帮助。谢谢。
    【解决方案2】:

    试试下面的查询 - Check it online

    DECLARE @Tab TABLE
    (
            itemid INT,
            itemprice INT,
            DateFrom Date
    )
    
    INSERT INTO @Tab VALUES (111,5000,'2018-01-01'),(111,8000,'2018-02-24'),(111,6000,'2018-03-12')
    
    SELECT *,ISNULL(
            (SELECT top 1 DATEADD(day,-1,DateFrom) 
                from @tab t1 
                WHERE t1.itemid= t2.itemid
                AND t1.Datefrom > t2.Datefrom) , GETDATE()) AS DateTo 
    FROM @tab t2
    

    【讨论】:

    • 在没有ORDER BY 的情况下执行SELECT top 1 毫无意义:它会产生不可预测的(准随机)结果。
    【解决方案3】:

    您需要将每条记录的DateTo 设置为大于其自己的DateFrom 的所有起始日期(对于相同的ItemId)中的“最小”,减去 1天”。

    对于那些找不到的,将其设置为 GetDate()。

    在 SQL 中:

    UPDATE PriceTable
    SET    DateTo = (SELECT DATEADD(d, -1, MIN(DateFrom))
                     FROM   PriceTable P2
                     WHERE  P2.ItemId   = P1.ItemId
                     AND    P2.DateFrom > P1.DateFrom)
    FROM PriceTable P1
    
    UPDATE PriceTable
    SET    DateTo = GETDATE()
    WHERE  DateTo IS NULL
    

    或合并为一个步骤:

    UPDATE PriceTable
    SET    DateTo = (SELECT ISNULL(DATEADD(d, -1, MIN(DateFrom)), GETDATE())
                     FROM   PriceTable P2
                     WHERE  P2.ItemId   = P1.ItemId
                     AND    P2.DateFrom > P1.DateFrom)
    FROM PriceTable P1
    

    【讨论】:

      【解决方案4】:

      如您所见,您可以在 adhoc basic 上创建 date_to 列。下面

      SELECT ItemId, ItemPrice, DateFrom,
      DATEADD(day, 1, lead(DateFrom,1,getdate()))  
      over (order by ItemId asc ,DateFrom asc) as date_to 
      FROM tbl 
      

      您可以将值更新为

      UPDATE tbl T2 SET dateto= 
      (SELECT 
      DATEADD(day, 1, lead(DateFrom,1,getdate()))  over (order by ItemId asc ,DateFrom asc) 
      FROM tbl T1 where T1.ItemId=T1.ItemId AND  T1.ItemId = T2.ItemId AND  T1.DateFrom = 
      T2.DateFrom)
      

      【讨论】:

        【解决方案5】:

        对于将来添加在插入新行时更新dateTo 的触发器,现在您必须选择以前的值DateFrom

        SELECT ItemId, ItemPrice, DateFrom,
         SELECT(DateFrom FROM tbl WHERE ItemId IN (
           SELECT TOP 1 ItemId FROM tbl WHERE tbl.ItemId = tbl1.ItemId 
             WHERE tbl.DateFrom < tbl1.DateFrom 
             ORDER BY tbl.DateFrom DESC)
        ) FROM tbl AS tbl1
        

        【讨论】:

        • 这并没有给 OP 一个答案;它给了他们一个想法。另外,当没有下一个值时,这如何解决问题?如果DateTo 的默认值设置为GETDATE(),它将在(最多)24 小时后失效。
        • @Larnu 更新了答案,它应该添加类似IFNULL(_QUERY_, GETDATE())
        • 恐怕这个查询不会运行;例如,SELECT 中的子查询需要用括号括起来(())。它也不满足最新的值,并且(有效的)查询将导致对表进行 3 次扫描;这似乎有点过头了。
        • 我的错误是我给了MySQL的解决方案提示。并且可以将扫描次数减少到2次,但是这样就不确定返回数据的正确性了
        • 这是一个 SQL Server 问题,而不是 MySQL。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-08-16
        • 2018-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-15
        相关资源
        最近更新 更多