SQL更改数据的长度

时间:2018-07-11 15:55:44

标签: sql sql-server sorting sql-server-2008

我有一张桌子:

ID   |     date     |   Location A   |   Location B
1234    2018-06-16        Chicago          Chicago
1234    2018-06-15        Chicago          Chicago
1234    2018-06-14        Chicago          Chicago
1234    2018-06-13        Chicago          Florida
1234    2018-06-12        Baltimore        Florida
1234    2018-06-11        California       Florida
1234    2018-06-10        California       Florida
4444    2018-06-16        Utah             Utah
4444    2018-06-15        Utah             Utah
4444    2018-06-14        Utah             Utah
4444    2018-06-13        Chicago          Utah
4444    2018-06-12        Baltimore        Utah
4444    2018-06-11        California       Florida
4444    2018-06-10        California       Florida
6214    2018-06-16        Baltimore        Baltimore
6214    2018-06-15        Baltimore        Baltimore
6214    2018-06-14        Baltimore        Baltimore
6214    2018-06-13        Baltimore        Florida
6214    2018-06-12        Baltimore        Florida
6214    2018-06-11        Baltimore        Florida

我的目标是要有一个新列来指示自位置A和位置B匹配以来的天数,但前提是之前它们不匹配并且位置B与当天或之前相同的位置相同将A更改为匹配项,并且“日期”为最新日期。

上表将如下所示

ID   |     date     |   Location A   |   Location B | Days Matched
1234    2018-06-16        Chicago          Chicago        3
4444    2018-06-16        Utah             Utah           3

ID 6214不会出现在表格中,因为位置A已经比位置B多1天了。

2 个答案:

答案 0 :(得分:0)

我可以毫不费力地给出的最佳尝试:

  • 获取每个ID的最新记录作为内部查询
  • 内部内部查询的不匹配日期最高
  • 外部查询拉出的计数大于不匹配日期。如果未匹配的日期为空,则它将获取所有记录

这是查询

SELECT A.ID, A.DATE, A.LOCATIONA, A.LOCATIONB,
    (SELECT COUNT(*) FROM TABLE V WHERE A.ID=V.ID AND (A.NOTMATCHEDDATE IS NULL OR V.NOTMATCHEDDATE>A.NOTMATCHEDDATE) AS CNT
FROM
(
SELECT ID, DATE, LOCATIONA, LOCATIONB,
    (
       SELECT MIN(DATE) FROM TABLE U WHERE T.ID=U.ID AND U.LOCATIONA<>U.LOCATIONB)
    ) AS NOTMATCHEDDATE,
FROM TABLE T
WHERE LOCATIONA=LOCATIONB AND 
  NOT EXISTS(SELECT * FROM TABLE S WHERE S.ID=T.ID AND S.DATE>T.DATE)
) A

答案 1 :(得分:0)

我自己并不遵守所有规则。特别是当芝加哥从未被“建议”时,我仍然不明白为什么要使用1234 / Chicago。这是一个刺:

with x as (
    select *,
        row_number() over (partition by ID order by DT desc) as rn,
        first_value(LocationA) over (partition by ID order by DT desc) as fv,
        count(*) over (partition by ID, LocationB) as cntB,
        count(case when LocationA = LocationB then 1 end) over (partition by ID) as cntE
    from T
), y as (
    select * from x where cntB > cntE
)
select cntE from y
where rn = 1 and DT = cast(getdate() as date);

这有点通用,但是我的印象是您的位置和建议顺序受到了足够的限制,可能会起作用。另外,我继续使用first_value(),意识到您可能无法使用它。

在此处找到一些DDL:http://rextester.com/CRST10642

编辑

这可能完全是错误的,但这是另一种想法:

with x as (
    select *,
        row_number() over (partition by ID order by DT desc) as rn,
        first_value(LocationA) over (partition by ID order by DT desc) as fv,
        count(*) over (partition by ID, LocationB) as cntB,
        count(case when LocationA = LocationB then 1 end) over (partition by ID) as cntE
    from T
), y as (
    select *,
        max(case when LocationA = fv then rn end) over (partition by ID) as maxA,
        max(case when LocationB = fv then rn end) over (partition by ID) as maxB    
    from x
)
select * from y where rn = 1 and maxB + 1 >= maxA;