您将如何使用 T-SQL 获得满足条件的顺序/连续记录的最大/最大计数

Posted

技术标签:

【中文标题】您将如何使用 T-SQL 获得满足条件的顺序/连续记录的最大/最大计数【英文标题】:How would you get the Largest / MAX COUNT of Sequential / Contiguous records meeting a Criteria using T-SQL 【发布时间】:2012-02-23 22:48:47 【问题描述】:

简而言之,我希望创建一个查询,以帮助我找到音乐会类型场地的最佳可用座位,就像 Ticketmaster.com 的“查找最佳可用座位”,其中要求找到最接近的座位数量到舞台,座位必须按顺序排列。

鉴于此示例表:

DECLARE @Seats TABLE
(
    SectionId   INT         NOT NULL,
    RowId       VARCHAR(2)  NOT NULL,
    SeatId      INT         NOT NULL,
    Priority    INT         NOT NULL, /* Used to determine closeness to the stage and/or order to search in */
    StatusCd    CHAR(1)     NOT NULL, /* A for Available, H for Held, P for Purchased, etc. */
    Cost        MONEY       NOT NULL
)

并给出这个脚本来填充表格:

DECLARE @SectionCounter INT
DECLARE @RowCounter INT
DECLARE @SeatCounter INT

SET     @SectionCounter = 1
SET     @RowCounter = 1

WHILE   @SectionCounter <= 10
BEGIN

    WHILE   @RowCounter <= 26
    BEGIN

        SET @SeatCounter = 1

        WHILE @SeatCounter <= 26
        BEGIN       

            INSERT INTO @Seats
            ( SectionId ,
              RowId ,
              SeatId ,
              Priority ,
              StatusCd ,
              Cost
            )
            VALUES 
            ( @SectionCounter ,
              CHAR(64 + @RowCounter) ,
              @SeatCounter ,
              1 ,
              (
                /* Randomly setting certain seats as purchased */
                SELECT  CASE
                        WHEN @SeatCounter IN 
                        (
                            1,2,9,10,
                            (ROUND(((26 - 1 -1) * RAND() + 1), 0)),
                            (ROUND(((26 - 1 -1) * RAND() + 1), 0)),
                            (ROUND(((26 - 1 -1) * RAND() + 1), 0)),
                            (ROUND(((26 - 1 -1) * RAND() + 1), 0)),
                            (ROUND(((26 - 1 -1) * RAND() + 1), 0)),
                            (ROUND(((26 - 1 -1) * RAND() + 1), 0)),
                            (ROUND(((26 - 1 -1) * RAND() + 1), 0))
                        )
                        THEN 'P' ELSE 'A' END) ,
              (
                SELECT  CASE
                        WHEN @SectionCounter IN (1,2)
                        THEN 75.00 ELSE 25.00 END
              )
            )

            SET @SeatCounter = @SeatCounter + 1

        END

        SET @RowCounter = @RowCounter + 1

    END

    SET     @RowCounter = 1
    SET @SectionCounter = @SectionCounter + 1

END

查找 x 个连续/连续座位的最佳查询是什么?

以下是我当前的解决方案,我的应用程序至少需要 3 次查询。

例如,如果客户要求 8 个下一个最佳可用座位,我将运行以下查询:

/* Get each sections available seat count */
SELECT  SectionId,
        Priority,
        COUNT(SeatId) AS 'Seat Count'
FROM    @Seats
WHERE   StatusCd = 'A' /* A = Available. */
GROUP BY SectionId, Priority
ORDER BY Priority

这会产生这样的结果集:

| SectionId | Priority | SeatCount |
|-----------|----------|-----------|
| 1         | 1        | 544       |
| 2         | 2        | 554       |
| 3         | 3        | 552       |

应用程序会说“是否有 8 个座位可用,优先级为 1?”使用上面的结果集,答案是肯定的,所以让我们获取相应部分的可用行数,即第 1 部分。这是查询:

SELECT  RowId,
        COUNT(SeatId) AS 'Seat Count'
FROM    @Seats
WHERE   SectionId = 1
        AND StatusCd = 'A'
GROUP BY RowId

这会产生这样的结果集:

| RowId | SeatCount |
|-------|-----------|
| A     | 21        |
| B     | 18        |
| C     | 22        |

应用程序会查看这些结果并从第一排开始提出相同的问题:“A 排有 8 个座位吗?”有了上面的结果,答案是肯定的,所以那个时候应用程序会用这个查询来查询 A 行的所有座位:

SELECT  *
FROM    @Seats
WHERE   SectionId = 1
AND     RowId = 'A'

这会产生这样的结果集:

| SectionId | RowId | SeatId | Priority | StatusCd | Cost  |
|-----------|-------|--------|----------|----------|-------|
| 1         | A     | 1      | 1        | P        | 75.00 |
| 1         | A     | 2      | 1        | P        | 75.00 |
| 1         | A     | 3      | 1        | A        | 75.00 |
| 1         | A     | 4      | 1        | A        | 75.00 |
| 1         | A     | 5      | 1        | A        | 75.00 |

那时,应用程序将遍历结果,试图连续找到 8 个座位,StatusCd 为“A”。

我确信有一种更有效的方法可以查询数据库中的连续记录,而无需加载整行并在代码中执行。

我对最佳解决方案的最佳猜测是在表上进行自连接,并对 SeatId 进行某种递增或类似的操作。

非常感谢任何帮助或建议。

【问题讨论】:

【参考方案1】:

这应该可以帮助您入门。就自我加入而言,您走在正确的轨道上,这是另一种方式。

这将为您提供具有相同优先级的前 8 个可用座位、分区、行,状态为“A”,按优先级、分区、行的优先顺序排列。如果我误解了什么,请纠正我。

DECLARE @number_seats AS INTEGER = 8;

WITH T1 AS (
    SELECT S.*,
           SeatId - ROW_NUMBER() OVER(PARTITION BY Priority, SectionId, RowId, StatusCd ORDER BY SeatId) AS grp
    FROM #seats AS S
),

T2 AS (
SELECT Priority    AS Priority,
       SectionId   AS Section,
       RowId       AS RowId,
       StatusCd    AS StatusCd, 
       MIN(SeatId) AS StartingSeat,
       MAX(SeatId) AS EndingSeat,
       COUNT(*)    AS Seats       
FROM T1
GROUP BY Priority, SectionId, RowId, StatusCd, grp
),

T3 AS (
    SELECT TOP 1 *
    FROM T2
    WHERE T2.Seats >= @number_seats and StatusCd = 'A'
    ORDER BY Priority, Section, RowId, StartingSeat
)
SELECT S.*
FROM T3 JOIN #seats AS S ON 
(
    T3.Priority = S.Priority AND
    T3.Section  = S.SectionId AND
    T3.RowId    = S.RowId AND
    S.SeatId BETWEEN T3.StartingSeat AND T3.StartingSeat + @number_seats - 1
)
ORDER BY Priority, Section, RowId, StartingSeat

结果:

SectionId   RowId SeatId      Priority    StatusCd Cost
----------- ----- ----------- ----------- -------- ---------------------
1           A     11          1           A        75.00
1           A     12          1           A        75.00
1           A     13          1           A        75.00
1           A     14          1           A        75.00
1           A     15          1           A        75.00
1           A     16          1           A        75.00
1           A     17          1           A        75.00
1           A     18          1           A        75.00

【讨论】:

很好的答案!我真的很惊讶它的执行速度有多快。你的答案正是我想要的。您已经真正重新创建了类似于 Ticketmaster.com 的“查找最佳可用座位”功能。太棒了! @RandyBurden - 没问题,我很高兴它对你有用 - 只要确保我在你接管 TicketMaster 时获得折扣

以上是关于您将如何使用 T-SQL 获得满足条件的顺序/连续记录的最大/最大计数的主要内容,如果未能解决你的问题,请参考以下文章

两个日期之间直到满足条件的天数之差

2021-06-30:给定长度为m的字符串aim,以及一个长度为n的字符串str ,问能否在str中找到一个长度为m的连续子串, 使得这个子串刚好由aim的m个字符组成,顺序无所谓, 返回任意满足条件

如何获得满足 mongodb 中字段所有条件的用户?

如何使用 Mongoose 进行查询,获得 N 个结果,但结合它找到的任何满足特定条件的文档?

T-SQL基础--TOP

如何通过使用 T-SQL 将两个整数值相除来获得浮点结果?