为 table 中的每个值创建 SQL 函数 运行

Make SQL function run for every value in table

这可能是一个新手问题,但我一辈子都弄不明白。

在解释我的存储过程之前,我将描述我的 table 并展示示例。 TicketBook table 包含已发给一个单元的所有 TicketBook。 TicketBooks 有 25 张票。

例如:

                        TicketBooks
                        -----------
TicketBookNum  |  TicketNum  |  UnitID  |  FirstTicket  |  LastTicket | Used
 ---------------------------------------------------------------------------
     101              101          120           101           126       Yes
     101              102          120           101           126       Yes
     101              103          120           101           126       No
     101              104          120           101           126       Yes
     etc...

这个table有数据库中所有已使用和未使用的门票。

不同的TicketBook可以同时发给不同的单位。所以TicketBook 101可以发给120单元,而TicketBook 151可以发给140

我的存储过程需要做的是 return 所有标记为未使用的票证,但还有一个大于标记为已使用的票证。

示例:

TicketBookNum  |  TicketNum | Used
----------------------------------
   101              101        Yes
   101              102        Yes
   101              103        No
   101              104        Yes
   101              105        Yes
   101              106        No
   101              107        No
   etc..

所以存储过程 returns Ticket 103,但不是 106107 因为在票簿中没有标记为已使用的票.

这是我目前正在使用的存储过程:

select TicketNum
from TicketBooks
where Used='No'
and TicketNum between 92226 and 92251
and TicketNum < (select top 1 TicketNum
                from TicketBooks
                where Used='Yes'
                and TicketNum between 92226 and 92251
                order by TicketNum desc)
order by TicketNum desc

这将 return TicketBook 82226 中丢失的票。如果我尝试更改 between 子句上的参数,则它不会 return 正确的结果。任何帮助将不胜感激。

试试这个

 ;WITH cte AS
(
 select TicketNum,ROW_NUMBER() OVER
    (PARTITION BY TicketBookNum,Used ORDER BY TicketNum) rn
from TicketBooks

)
SELECT * FROM cte 
where Used='No' AND rn =1 

例子

CREATE TABLE #t (ticket INT ,ticketno INT, fla VARCHAR(10))

INSERT INTO #t VALUES(1,1,'yes'),
(1,2,'yes'),
(1,4,'No'),
(1,5,'No')

;WITH cte AS
(

SELECT *,ROW_NUMBER() OVER(PARTITION BY ticket,fla ORDER BY ticketno) rn FROM #t 
 )

 SELECT * FROM cte WHERE fla ='no'AND rn =1 
select TicketNum
from TicketBooks as t
where Used='No'
    and TicketNum between 92226 and 92251
    and exists (
        select 1
        from TicketBooks as t2
        where t2.Used='Yes'
            /* not sure if you actually want to restrict the range here */
            and t2.TicketNum between 92226 and 92251
            and t2.TicketNum > t.TicketNum
    )
order by TicketNum desc

我不明白你是想在票簿内搜索还是在明确的范围内搜索还是什么。但我写这篇文章是为了向您展示 EXISTS 选项。您还可能会发现 < ANY (...)< ALL (...) 将来会有用。很多人忽略了这些。

我相信我明白你想做什么。我认为你缺少的是你的子查询没有映射到你的外部查询的票簿。所以你想要这样的东西:

select TicketNum
from TicketBooks a
where Used='No'
and TicketNum < (select MAX(b.TicketNum)
            from TicketBooks b
            where b.Used='Yes'
            and b.TicketBookNum = a.TicketBookNum)
order by TicketNum desc

您可以使用常见的 table 表达式来包装范围限制并执行这样的存在查询:

;with cte as (
    select * from TicketBooks where TicketNum between 101 and 126
    )

select * from cte where Used = 'no'
and exists (
    select 1 
    from cte t
    where t.TicketNum > cte.ticketnum
    and t.used='yes'
    )

这仍然限于硬编码范围;更好的选择可能是从源 table.

中的 FirstTicket/LastTicket 值构建范围