我正在使用SQL Server 2008 R2并且我有以下数据集:
+---------+--------------+--------------+----------+------------+------------+
| Dossier | refmouvement | refadmission | refunite | datedeb | datefin |
+---------+--------------+--------------+----------+------------+------------+
| P001234 | 2567 | 1234 | 227 | 2012-01-01 | 2012-01-02 |
| P001234 | 2568 | 1234 | 227 | 2012-01-02 | 2012-01-03 |
| P001234 | 2569 | 1234 | 224 | 2012-01-03 | 2012-01-06 |
| P001234 | 2570 | 1234 | 232 | 2012-01-06 | 2012-01-10 |
| P001234 | 2571 | 1234 | 232 | 2012-01-10 | 2012-01-15 |
| P001234 | 2572 | 1234 | 232 | 2012-01-15 | 2012-01-20 |
| P001234 | 2573 | 1234 | 232 | 2012-01-20 | 2012-01-25 |
| P001234 | 2574 | 1234 | 224 | 2012-01-25 | 2012-01-29 |
| P001234 | 2575 | 1234 | 227 | 2012-01-29 | 2012-02-05 |
| P001234 | 2576 | 1234 | 227 | 2012-02-05 | 2012-02-10 |
| P001234 | 2577 | 1234 | 232 | 2012-02-10 | 2012-02-15 |
| P001234 | 2578 | 1234 | 201 | 2012-02-15 | 2012-02-26 |
+---------+--------------+--------------+----------+------------+------------+
此数据集按datedeb
排序,也称为startdate
。
您可以注意到这是一个连续的数据集,其中datefin
等于下一行的datedeb
我需要创建一个ID
列,根据refunite
和datedeb
列提供唯一ID,如下所示:
+----+---------+--------------+--------------+----------+------------+------------+
| ID | Dossier | refmouvement | refadmission | refunite | datedeb | datefin |
+----+---------+--------------+--------------+----------+------------+------------+
| 1 | P001234 | 2567 | 1234 | 227 | 2012-01-01 | 2012-01-02 |
| 1 | P001234 | 2568 | 1234 | 227 | 2012-01-02 | 2012-01-03 |
| 2 | P001234 | 2569 | 1234 | 224 | 2012-01-03 | 2012-01-06 |
| 3 | P001234 | 2570 | 1234 | 232 | 2012-01-06 | 2012-01-10 |
| 3 | P001234 | 2571 | 1234 | 232 | 2012-01-10 | 2012-01-15 |
| 3 | P001234 | 2572 | 1234 | 232 | 2012-01-15 | 2012-01-20 |
| 3 | P001234 | 2573 | 1234 | 232 | 2012-01-20 | 2012-01-25 |
| 4 | P001234 | 2574 | 1234 | 224 | 2012-01-25 | 2012-01-29 |
| 5 | P001234 | 2575 | 1234 | 227 | 2012-01-29 | 2012-02-05 |
| 5 | P001234 | 2576 | 1234 | 227 | 2012-02-05 | 2012-02-10 |
| 6 | P001234 | 2577 | 1234 | 232 | 2012-02-10 | 2012-02-15 |
| 7 | P001234 | 2578 | 1234 | 201 | 2012-02-15 | 2012-02-26 |
+----+---------+--------------+--------------+----------+------------+------------+
我无法绕过RANK()
,ROW_NUMBER()
或DENSE_RANK()
功能,或者可以实现这一目标的组合,我到处寻找,但我找不到任何东西,也许我没有使用正确的关键字,但我无法弄清楚
任何帮助将不胜感激
感谢。
这是我到目前为止尝试过的代码:
SELECT
ROW_NUMBER() over(order by t1.[datedeb]) as [ID1],
dense_Rank() over(partition by t1.[refunite] order by t1.[datedeb]) as [ID2],
t1.[Dossier]
,t1.[refmouvement]
,t1.[refadmission]
,t1.[refunite]
,t1.[datedeb]
,t1.[datefin]
,t2.[refmouvement] as [prev_refmouvement]
,t2.refunite as prev_refunite
FROM [sometable] t1
LEFT OUTER JOIN [sometable] t2 /*self join*/
ON t2.datefin = t1.datedeb
AND t1.[refadmission] = t2.[refadmission]
ORDER BY
t1.[datedeb]
这就是它给我的东西:
+-----+-----+---------+--------------+--------------+----------+------------+------------+-------------------+---------------+
| ID1 | ID2 | Dossier | refmouvement | refadmission | refunite | datedeb | datefin | prev_refmouvement | prev_refunite |
+-----+-----+---------+--------------+--------------+----------+------------+------------+-------------------+---------------+
| 1 | 1 | P001234 | 2567 | 1234 | 227 | 2012-01-01 | 2012-01-02 | NULL | NULL |
| 2 | 2 | P001234 | 2568 | 1234 | 227 | 2012-01-02 | 2012-01-03 | 2567 | 227 |
| 3 | 1 | P001234 | 2569 | 1234 | 224 | 2012-01-03 | 2012-01-06 | 2568 | 227 |
| 4 | 1 | P001234 | 2570 | 1234 | 232 | 2012-01-06 | 2012-01-10 | 2569 | 224 |
| 5 | 2 | P001234 | 2571 | 1234 | 232 | 2012-01-10 | 2012-01-15 | 2570 | 232 |
| 6 | 3 | P001234 | 2572 | 1234 | 232 | 2012-01-15 | 2012-01-20 | 2571 | 232 |
| 7 | 4 | P001234 | 2573 | 1234 | 232 | 2012-01-20 | 2012-01-25 | 2572 | 232 |
| 8 | 2 | P001234 | 2574 | 1234 | 224 | 2012-01-25 | 2012-01-29 | 2573 | 232 |
| 9 | 3 | P001234 | 2575 | 1234 | 227 | 2012-01-29 | 2012-02-05 | 2574 | 224 |
| 10 | 4 | P001234 | 2576 | 1234 | 227 | 2012-02-05 | 2012-02-10 | 2575 | 227 |
| 11 | 5 | P001234 | 2577 | 1234 | 232 | 2012-02-10 | 2012-02-15 | 2576 | 227 |
| 12 | 1 | P001234 | 2578 | 1234 | 201 | 2012-02-15 | 2012-02-26 | 2577 | 232 |
+-----+-----+---------+--------------+--------------+----------+------------+------------+-------------------+---------------+
Shaz
答案 0 :(得分:2)
DECLARE @Results TABLE(
RowNum INT PRIMARY KEY,
refunite INT NOT NULL,
datedeb DATETIME NOT NULL
);
INSERT @Results (RowNum, refunite, datedeb)
SELECT ROW_NUMBER() OVER(ORDER BY datedeb) AS RowNum,
refunite,
datedeb
FROM dbo.MyTable;
WITH CTERecursive
AS (
SELECT crt.RowNum,
crt.refunite,
crt.datedeb,
1 AS Rnk -- Starting rank
FROM @Results crt
WHERE crt.RowNum = 1
UNION ALL
SELECT crt.RowNum,
crt.refunite,
crt.datedeb,
CASE WHEN prev.refunite = crt.refunite THEN prev.Rnk ELSE prev.Rnk + 1 END
FROM @Results crt INNER JOIN CTERecursive prev ON crt.RowNum = prev.RowNum + 1
)
SELECT *
FROM CTERecursive
-- OPTION(MAXRECURSION 1000); -- Uncomment this line if you change the number of recursion levels allowed (default 100)
结果:
RowNum refunite datedeb Rnk
----------- ----------- ----------------------- ---
1 227 2012-01-01 00:00:00.000 1
2 227 2012-01-02 00:00:00.000 1
3 224 2012-01-03 00:00:00.000 2
4 232 2012-01-06 00:00:00.000 3
5 232 2012-01-10 00:00:00.000 3
6 232 2012-01-15 00:00:00.000 3
7 232 2012-01-20 00:00:00.000 3
8 224 2012-01-25 00:00:00.000 4
9 227 2012-01-29 00:00:00.000 5
10 227 2012-02-05 00:00:00.000 5
11 232 2012-02-10 00:00:00.000 6
12 201 2012-02-15 00:00:00.000 7
答案 1 :(得分:2)
当然,你可以在WITH中有多个表,从而消除了表变量。 根据Bogdan Sahleans的回答,您可以这样重写:
WITH CTEHelper AS
(SELECT ROW_NUMBER() OVER(ORDER BY datedeb) AS RowNum,
refunite,
datedeb
FROM dbo.Sometable),
CTERecursive AS (
SELECT crt.RowNum,
crt.refunite,
crt.datedeb,
1 AS Id -- Starting rank
FROM CTEHelper crt
WHERE crt.RowNum = 1
UNION ALL
SELECT crt.RowNum,
crt.refunite,
crt.datedeb,
CASE WHEN prev.refunite = crt.refunite THEN prev.Id ELSE prev.Id + 1 END
FROM CTEHelper crt INNER JOIN CTERecursive prev ON crt.RowNum = prev.RowNum + 1
)
SELECT crt.id,
s.*
FROM CTERecursive crt
JOIN Sometable s ON s.refunite = crt.refunite AND s.datedeb = crt.datedeb
答案 2 :(得分:1)
with sometable as (
select *
from (
values ('P001234', 2567, 1234, 227, cast('2012-01-01' as date), cast('2012-01-02' as date)),
('P001234', 2568, 1234, 227, cast('2012-01-02' as date), cast('2012-01-03' as date)),
('P001234', 2569, 1234, 224, cast('2012-01-03' as date), cast('2012-01-06' as date)),
('P001234', 2570, 1234, 232, cast('2012-01-06' as date), cast('2012-01-10' as date)),
('P001234', 2571, 1234, 232, cast('2012-01-10' as date), cast('2012-01-15' as date)),
('P001234', 2572, 1234, 232, cast('2012-01-15' as date), cast('2012-01-20' as date)),
('P001234', 2573, 1234, 232, cast('2012-01-20' as date), cast('2012-01-25' as date)),
('P001234', 2574, 1234, 224, cast('2012-01-25' as date), cast('2012-01-29' as date)),
('P001234', 2575, 1234, 227, cast('2012-01-29' as date), cast('2012-02-05' as date)),
('P001234', 2576, 1234, 227, cast('2012-02-05' as date), cast('2012-02-10' as date)),
('P001234', 2577, 1234, 232, cast('2012-02-10' as date), cast('2012-02-15' as date)),
('P001234', 2578, 1234, 201, cast('2012-02-15' as date), cast('2012-02-26' as date))
) t (Dossier, refmouvement, refadmission, refunite, datedeb, datefin)
), pos as (
select d.*, (case when d2.refunite is null then null
when d2.refunite != d.refunite then d2.datedeb
else d.datedeb end) as forward,
(case when d3.refunite is null then null
when d3.refunite != d.refunite then d3.datedeb
else d.datedeb end) as backward
from sometable d
left outer join sometable d2 on d.refadmission = d2.refadmission and d.datefin = d2.datedeb
left outer join sometable d3 on d.refadmission = d3.refadmission and d.datedeb = d3.datefin
)
select dense_rank() over (order by isnull((select min(datedeb)
from pos
where refadmission = t.refadmission
and refunite = t.refunite
and datedeb > t.datedeb
and datedeb = backward
and ((t.datedeb = t.backward and t.datedeb = t.forward)
or t.datedeb != t.backward or t.backward is null)
and datedeb != forward), datedeb)) as ID,
Dossier, refmouvement, refadmission, refunite, datedeb, datefin
from pos t
order by datedeb