如何选择一组特定的行,然后选择与原始行相关的下一行

时间:2014-04-22 13:36:25

标签: sql-server tsql

我不知道我现在的数据集是否可以找到它,或者我认为它是否可能。

我想要完成的是获取status = 2 or 7的所有行获取日期,然后获取具有不同状态的下一行以获取dateinterval并获取状态所具有的nuber天数。

的数据集

id_compromiso|fecha      |id_actividad|status
-------------+-----------+------------+----------
32            2013-12-10  359          2
32            2013-12-16  380          5
32            2013-12-18  401          7
32            2013-12-24  485          8
58            2013-12-02  248          2
58            2013-12-03  254          2
58            2013-12-10  360          2
58            2013-12-10  378          5
58            2013-12-12  395          2

我尝试了什么:

SQL查询:

WITH pausa AS (
        SELECT tmp.id_compromiso, tmp.fecha, MIN(tact.id_actividad) as id_actividad
        FROM Actividades as tact 
        INNER JOIN (
            SELECT act.id_compromiso, CAST(act.fecha as date) as fecha 
            FROM actividades as act 
            WHERE act.[status]=7
        ) as tmp 
        ON(tmp.id_compromiso = tact.id_compromiso AND tmp.fecha = CAST(tact.fecha as date))
        WHERE tact.[status]=7
        GROUP BY tmp.id_compromiso, tmp.fecha
    ),
    revision AS (
        SELECT tmp.id_compromiso, tmp.fecha, MIN(tact.id_actividad) as id_actividad
        FROM Actividades as tact 
        INNER JOIN (
            SELECT act.id_compromiso, CAST(act.fecha as date) as fecha 
            FROM actividades as act 
            WHERE act.[status]=2
        ) as tmp 
        ON(tmp.id_compromiso = tact.id_compromiso AND tmp.fecha = CAST(tact.fecha as date))
        WHERE tact.[status]=2
        GROUP BY tmp.id_compromiso, tmp.fecha
    )
SELECT * FROM revision ORDER BY id_compromiso;

但真的在运行我的想法是如何从表中获得具有不同状态的下一个项目......

2 个答案:

答案 0 :(得分:2)

-- First, it extends actividades to include the minimum fecha for the status
-- on the compromiso; this is min(fecha) in the partition by compromiso/status

WITH status_start AS(
SELECT *, MIN(fecha) OVER (PARTITION BY id_compromiso, status) sStart
FROM actividades 
),

-- Then, join the extended actividades table with itself (aliased a and b) by compromiso but status 2,7 with status not 2,7 
-- (this is the AND a.STATUS IN (2,7)  AND b.STATUS NOT IN(2,7) in the join clause)
-- and making sure it's a later status (the a.sStart <b.sStart bit) 
-- at this point also calculates the date difference in days

status_start_end AS(
SELECT a.*,b.sStart sEnd, DATEDIFF(d, a.sStart, b.sStart) AS sDiff FROM status_start a
JOIN status_start b ON (a.id_compromiso =b.id_compromiso AND a.STATUS IN (2,7)  AND b.STATUS NOT IN(2,7) AND a.sStart <b.sStart))

-- Finaly as the previous query would have day difference in relation to ALL later status, we need to select only the minimum difference
-- as this is when the status actually change. We also need to eliminate duplicates using 'distinct; 
-- as it could be many entries for the same status and
-- also many later status.


SELECT DISTINCT id_compromiso, status ,
MIN(sDiff)  OVER (PARTITION BY id_compromiso) "Nr. of days in status" 
FROM status_start_end

答案 1 :(得分:0)

如果不了解有关上下文的更多信息,很难提供合适的答案,但这样的事情可能有所帮助:

SELECT TOP 1 id_compromiso, fecha, id_actividad, status
FROM Actividades
WHERE CAST(fecha AS DATE)>( SELECT  MAX(CAST(fecha AS DATE))
                            FROM Actividades
                                WHERE status IN (2,7))
AND status NOT IN (2,7)
ORDER BY CAST(fecha AS DATE) DESC

我已经设置了一个SQL小提琴here