【问题标题】:TSQL Get table results by joining the same table multiple timesTSQL通过多次加入同一个表来获取表结果
【发布时间】:2017-09-28 16:21:16
【问题描述】:

我有以下几点:

DECLARE @p_StartDate    DATETIME
DECLARE @p_EndDate      DATETIME

DECLARE @SC TABLE
(
TimeStamp DATETIME,
Action NVARCHAR,
StudyID INT NOT NULL,
ChamberID INT NOT NULL
)

INSERT INTO @SC (TimeStamp, Action, StudyID, ChamberID)
SELECT '2017-03-28 14:05:08.040', 'I', 155, 3335
UNION ALL
SELECT '2017-03-28 14:05:08.047',   'I', 155, 3336
UNION ALL
SELECT '2017-03-28 14:36:00.157',   'I', 155, 6418
UNION ALL
SELECT '2017-03-30 13:15:04.607',   'I', 155, 3337
UNION ALL
SELECT '2017-03-30 13:15:04.607',   'I', 155, 3338
UNION ALL
SELECT '2017-04-04 13:40:28.580',   'D', 155, 3338
UNION ALL
SELECT '2017-04-04 14:48:43.593',   'D', 155, 3337
UNION ALL
SELECT '2017-04-17 20:56:07.540',   'D', 155, 3335
UNION ALL
SELECT '2017-04-17 21:05:09.507',   'I', 155, 3335

Action = 'I' 表示已分配,'D' 表示已解除分配。

在给定查询周期的情况下,我需要找到分配给研究的所有分庭。例如,如果 @p_StartDate = '20170101' AND @p_EndDate = '20170102' 那么它应该不会产生任何结果。

如果 @p_StartDate = '20170328' 和 @p_EndDate = '20170331' 则应返回以下内容:

ChamberId   DateAllocated 
3335        2017-03-28 14:05:08.040
3336        2017-03-28 14:05:08.047
6418        2017-03-28 14:36:00.157
3337        2017-03-30 13:15:04.607
3338        2017-03-30 13:15:04.607

如果 @p_StartDate = '20170328' 和 @p_EndDate = '20170431' 则应返回以下内容:

ChamberId   DateAllocated 
3335        2017-03-28 14:05:08.040
3336        2017-03-28 14:05:08.047
6418        2017-03-28 14:36:00.157
3337        2017-03-30 13:15:04.607
3338        2017-03-30 13:15:04.607
3335        2017-04-17 21:05:09.507

但是,如果 @p_StartDate = '20170418' 和 @p_EndDate = '20170431' 那么:

ChamberId   DateAllocated 
3336        2017-03-28 14:05:08.047
6418        2017-03-28 14:36:00.157
3335        2017-04-17 21:05:09.507

由于 3335 室的第一次分配于 2017-04-17 20:56:07.540 被释放,3338 和 3337 室在 2017-04-04 13:40:28.580 和 2017-04-04 14 被释放分别为:48:43.593。

如果可能的话,我想避免使用游标,所以我尝试了:

SELECT  A.TimeStamp, A.Action, A.StudyID, A.ChamberID
FROM    @SC A   
        LEFT JOIN 
        (
            SELECT *
            FROM @SC
            WHERE Action = 'D'
        ) AS B
        ON A.ChamberID = B.ChamberID
        AND A.StudyID = B.StudyID
        AND A.TimeStamp < B.TimeStamp

WHERE (A.Action = 'I' AND A.TimeStamp < @p_EndDate)
AND NOT (A.Action = 'D' AND A.TimeStamp < @p_StartDate)
AND A.StudyID = 155
AND B.TimeStamp IS NULL
ORDER BY ChamberID

任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 对于同一个研究,一个腔室可能会被分配,然后被释放,然后被分配,然后被重复释放。
  • 您好史蒂夫,感谢您的帮助。它非常接近所需的内容,但存在一个问题。我设置了 p_StartDate = '4/03/2017 1:15:05 PM' p_EndDate = '4/18/2017 2:15:05 PM',然后我也应该把 Chamber 3337 拿回来,因为 3337 在p_StartDate。

标签: sql sql-server-2008 tsql left-join common-table-expression


【解决方案1】:

如果我理解正确,以下应该是(或接近)您需要的:

SELECT
    A.TimeStamp,
    A.Action,
    A.StudyID,
    A.ChamberID
FROM
    @SC A
WHERE
    a.Action = 'I'
    AND a.TimeStamp < @p_EndDate
    AND NOT EXISTS (SELECT 1 from @SC B
                    WHERE B.TimeStamp > a.Timestamp
                    AND B.TimeStamp < @p_StartDate
                    AND B.ChamberID = A.ChamberID
                    AND B.StudyID = A.StudyID --Note on this below
                    AND B.Action = 'D')
    AND A.StudyID = 155
ORDER BY
    A.TimeStamp

试试rextester.com/SIFD43479

我不完全确定 &lt; 运算符是否真的是您想要的。根据您对该行的需求,您可能需要将时间戳转换为日期(即删除时间部分)并改用&lt;=

注意: 不熟悉这个数据集代表什么或者你到底在做什么,AND B.StudyID = A.StudyID 行似乎是多余的,在某些情况下甚至可能导致错误的结果。如果 ChamberID 仅与之前分配的 StudyID 相关,并且不能同时分配给两个 StudyID,那么我认为这很好。

【讨论】:

  • 您好史蒂夫,感谢您的帮助。它非常接近要求,但存在一个问题。
  • 我设置了 p_StartDate = '4/03/2017 1:15:05 PM' p_EndDate = '4/18/2017 2:15:05 PM',然后我应该让房间 3337 回来也因为 3337 在 p_StartDate 之后被释放。
  • 这对我来说比我第一次看到它时更有意义。正在更新中。
  • 感谢史蒂夫,工作完美!我也对如何在子查询中使用过滤器有了更多的了解。我不想让问题复杂化,因此我没有包含其他 StudyID。完全有可能将一个房间分配给一项研究并分配给另一项研究,因此 B.StudyID = A.StudyID 很重要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 2017-10-27
相关资源
最近更新 更多