T-SQL итеративно проверяет историю - PullRequest
1 голос
/ 26 июля 2011

Как сделать выбор на основе предыдущей истории предмета?

Например, я пытаюсь выбрать элемент, который имеет значение 1, ранее имел значение 10, а ранее - значение 1 = 3.

    WITH Items (itemId, date, val) AS (
      SELECT 1, CONVERT(datetime, '5/1/2011'), 6 UNION ALL
      SELECT 2, CONVERT(datetime, '5/1/2011'), 5 UNION ALL
      SELECT 3, CONVERT(datetime, '5/1/2011'), 1 UNION ALL
      SELECT 1, CONVERT(datetime, '6/1/2011'), 1 UNION ALL
      SELECT 2, CONVERT(datetime, '6/1/2011'), 10 UNION ALL
      SELECT 3, CONVERT(datetime, '6/1/2011'), 10 UNION ALL
      SELECT 1, CONVERT(datetime, '7/1/2011'), 1 UNION ALL
      SELECT 2, CONVERT(datetime, '7/1/2011'), 1 UNION ALL
      SELECT 3, CONVERT(datetime, '7/1/2011'), 1 
    )
    select distinct itemId from Items where val = 1
    --and a previous date val = 10
    --and a previous previous date val = 1

Ответы [ 3 ]

0 голосов
/ 26 июля 2011

Поскольку у вас есть требование Значение на предыдущую дату , вы должны использовать ROW_NUM Упорядочение по ItemId и дате.

Затем вы делаете два self join на Id плюс RowNum присоединяется к предыдущему (действует до предыдущей даты) и добавляет предложения WHERE к 1-10-1

WITH Items_Original (itemId, date, val) AS 
(
    SELECT 1, CONVERT(datetime, '5/1/2011'), 6 UNION ALL
    SELECT 2, CONVERT(datetime, '5/1/2011'), 5 UNION ALL
    SELECT 3, CONVERT(datetime, '5/1/2011'), 1 UNION ALL
    SELECT 1, CONVERT(datetime, '6/1/2011'), 1 UNION ALL
    SELECT 2, CONVERT(datetime, '6/1/2011'), 10 UNION ALL
    SELECT 3, CONVERT(datetime, '6/1/2011'), 10 UNION ALL
    SELECT 1, CONVERT(datetime, '7/1/2011'), 1 UNION ALL
    SELECT 2, CONVERT(datetime, '7/1/2011'), 1 UNION ALL
    SELECT 3, CONVERT(datetime, '7/1/2011'), 1 
),
Items As
(
    Select 
        ROW_NUMBER() OVER(ORDER BY ItemId, Date) AS RowNum, * 
        FROM Items_Original
) 
select * 
from Items I1
    Inner JOIN Items I2
        On I1.itemId = I2.itemId
        And I1.RowNum = I2.RowNum-1
    Inner JOIN Items I3
        On I2.itemId = I3.itemId
        And I2.RowNum = I3.RowNum-1
Where 1=1
    And I1.val = 1
    And I2.val = 10
    And I3.val = 1
0 голосов
/ 26 июля 2011
 WITH Items (itemId, date, val) AS (
      SELECT 1, CONVERT(datetime, '5/1/2011'), 6 UNION ALL
      SELECT 2, CONVERT(datetime, '5/1/2011'), 5 UNION ALL
      SELECT 3, CONVERT(datetime, '5/1/2011'), 1 UNION ALL
      SELECT 1, CONVERT(datetime, '6/1/2011'), 1 UNION ALL
      SELECT 2, CONVERT(datetime, '6/1/2011'), 10 UNION ALL
      SELECT 3, CONVERT(datetime, '6/1/2011'), 10 UNION ALL
      SELECT 1, CONVERT(datetime, '7/1/2011'), 1 UNION ALL
      SELECT 2, CONVERT(datetime, '7/1/2011'), 1 UNION ALL
      SELECT 3, CONVERT(datetime, '7/1/2011'), 1 
    ),
cte as
(
    select *, row_number() over(partition by itemId order by date) [rn]
    from Items t
)

select distinct a.itemId
from cte a
join cte b on b.rn = a.rn + 1 and b.itemId = a.itemId
join cte c on c.rn = b.rn + 1 and c.itemId = a.itemId
where a.val = 1 and b.val = 10 and c.val = 1
0 голосов
/ 26 июля 2011

Это даст конкретный ответ, который вы ищете.Не уверен, насколько это полезно в абстрактном смысле.Вы всегда будете искать предметы, которые имеют ровно 3 значения, 1-10-1?

SELECT
   A.itemID
FROM
   Items A
   INNER JOIN Items B ON A.itemID = B.itemID AND B.val = 10
   INNER JOIN Items C ON B.itemID = C.itemID AND C.val = 1
WHERE
   A.val = 1
...