0

我的表有以下数据

name    price    date
aa        10    1/1/2013
bb        12    1/1/2013
cc        35    1/1/2013
aa        23    1/2/2013
cc        30    1/2/2013
bb        35    1/2/2013
cc        2     1/3/2013
aa        40    1/3/2013
bb        50    1/3/2013
aa        45    1/4/2013
cc        60    1/4/2013
bb        65    1/4/2013

所以我的输出应该是

name    price    date
aa        23    1/2/2013
aa        40    1/3/2013
aa        45    1/4/2013
bb        35    1/2/2013
bb        50    1/3/2013
bb        65    1/4/2013

"cc" 不应出现,因为它的价格在 2013 年 1 月 3 日 2 日下跌


编辑

这是一些让你开始的小提琴。

4

4 回答 4

1

即使我的结果不同(可能是因为日期混淆),这也应该有效:

WITH Invalids AS(
  SELECT [name]
  FROM dbo.Table1 t1
  WHERE EXISTS(
    SELECT 1 FROM dbo.Table1 t2
    WHERE t1.name = t2.name
    AND t1.date >= t2.date
    AND DATEDIFF(dd,t2.date, t1.date) <= 3
    AND t2.price > t1.price
  )
)
SELECT * FROM dbo.Table1 t1
WHERE NOT EXISTS(
    SELECT 1 FROM Invalids i WHERE i.name=t1.name
)
ORDER BY name,price, date

Demonstration

于 2013-09-25T13:11:06.263 回答
0

这是使用该LAG功能的更有效的解决方案,

在这里提琴

WITH [Movements] AS (
SELECT
           [Price] - LAG([Price], 1, [Price]) OVER (
               PARTITION BY name 
               ORDER BY DATE) [Movement],
           [Name]
    FROM
           [Prices]
    WHERE
           [Date] BETWEEN '1/1/2013' AND '1/4/2013')
SELECT
            P.[Name],
            P.[Price],
            P.[Date]
    FROM
            [Prices] P
    WHERE
            NOT EXISTS
            (
               SELECT 1
                   FROM [Movements]
                   WHERE
                           [Name] = P.[Name]
                       AND
                           [Movement] < 0
            )
        AND
            [Date] BETWEEN '1/1/2013' AND '1/4/2013' 
    ORDER BY
            [Name] ASC,
            [Date] ASC;

但是,既然你制定了这个动作,你也可以把它包括在结果中,

像这样

WITH [Movements] AS (
SELECT
           [Price] - LAG([Price], 1, [Price]) OVER (
               PARTITION BY name 
               ORDER BY DATE) [Movement],
           [Name],
           [Date]
    FROM
           [Prices]
    WHERE
           [Date] BETWEEN '1/1/2013' AND '1/4/2013')
SELECT
            P.[Name],
            P.[Price],
            P.[Date],
            M.[Movement]
    FROM
            [Prices] P
        JOIN
            [Movements] M
               ON M.[Date] = P.[Date] AND M.[Name] = P.[Name]
    WHERE
            NOT EXISTS
            (
               SELECT 1
                   FROM [Movements]
                   WHERE
                           [Name] = P.[Name]
                       AND
                           [Movement] < 0
            )
        AND
            P.[Date] BETWEEN '1/1/2013' AND '1/4/2013' 
    ORDER BY
            P.[Name] ASC,
            P.[Date] ASC;
于 2013-09-25T14:06:03.393 回答
0
--Date to be used as "today"
DECLARE @refDate as smalldatetime = '1-4-2013'

SELECT a.Name,
    a.[Date],
    a.Price AS 'PriceToday',
    b.Price AS 'PriceYesterday',
    c.Price AS 'Price2DaysAgo'
FROM @prices a
LEFT JOIN @prices b ON b.Name = a.Name AND b.[Date] = DATEADD(DAY, -1, a.[Date])
LEFT JOIN @prices c ON c.Name = a.Name AND c.[Date] = DATEADD(DAY, -2, a.[Date])
WHERE a.[Date] = @refDate
AND a.Price > b.Price
AND b.Price > c.Price

这将返回以下内容:

+--------+------------+------------+---------------- +---------------+
| 姓名 | 日期 | 今日价格 | 价格昨天 | 价格2天前 |
+--------+------------+------------+---------------- +---------------+
| 啊 | 2013-01-04 | 45.0000 | 40.0000 | 23.0000 |
| bb | 2013-01-04 | 65.0000 | 50.0000 | 35.0000 |
+--------+------------+------------+---------------- +---------------+

如果您将 @refDate 设置为 '1-3-2013',它将返回:

+--------+------------+------------+---------------- +---------------+
| 姓名 | 日期 | 今日价格 | 价格昨天 | 价格2天前 |
+--------+------------+------------+---------------- +---------------+
| 啊 | 2013-01-03 | 40.0000 | 23.0000 | 10.0000 |
| bb | 2013-01-03 | 50.0000 | 35.0000 | 12.0000 |
+--------+------------+------------+---------------- +---------------+

输出格式不完全符合您的要求,但 SELECT 的前提应该足以作为可延展的代码片段。

于 2013-09-25T13:40:54.553 回答
0
;with cte as (select *, ROW_NUMBER() over (partition by name order by date) rn from yourtable)
select c1.*, c2.price, c2.date, c3.price, c3.date 
from cte c1
    inner join cte c2 on c1.name = c2.name 
         and c1.rn+1=c2.rn
         and c1.price<c2.price
    inner join cte c3 on c2.name = c3.name 
         and c2.rn+1=c3.rn
         and c2.price<c3.price

或者,如果您希望结果为行,

;with cte as (select *, ROW_NUMBER() over (partition by name order by date) rn from yourtable),
cte2 as (select c1.*, 
    c2.price price2, c2.date date2,
    c3.price price3, c3.date date3
from cte c1
inner join cte c2 on c1.name = c2.name 
     and c1.rn+1=c2.rn
     and c1.price<c2.price
inner join cte c3 on c2.name = c3.name 
     and c2.rn+1=c3.rn
     and c2.price<c3.price
)
select name, price, date, rn from cte2
union all
select name, price2, date2, rn from cte2
union all
select name, price3, date3, rn from cte2
order by name, rn

在 SQL 2012 中,您可以使用LAG

于 2013-09-25T13:07:19.737 回答