Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Tsql 不使用光标处理句点和日期_Tsql_Date_Fetch_Cursors_Period - Fatal编程技术网

Tsql 不使用光标处理句点和日期

Tsql 不使用光标处理句点和日期,tsql,date,fetch,cursors,period,Tsql,Date,Fetch,Cursors,Period,我想解决这个问题,避免使用游标获取 问题来了 1st Table/quantity ------------------ periodid periodstart periodend quantity 1 2010/10/01 2010/10/15 5 2st Table/sold items ----------------------- periodid periodstart periodend solditems 14343 2010/10/05 201

我想解决这个问题,避免使用游标获取

问题来了

1st Table/quantity
------------------
periodid periodstart periodend quantity

1        2010/10/01 2010/10/15    5


2st Table/sold items
-----------------------
periodid periodstart periodend solditems

14343    2010/10/05 2010/10/06    2
现在我想获得以下视图或只是查询结果

Table Table/stock
-----------------------
periodstart periodend itemsinstock

2010/10/01 2010/10/04      5

2010/10/05 2010/10/06      3

2010/10/07 2010/10/15      5
如果不使用游标,或者不使用单一日期而不是句点,似乎不可能解决这个问题

我将感谢任何帮助


谢谢

约翰,你能做的就是做一个WHILE循环。在循环之前声明并初始化两个变量,一个是开始日期,另一个是结束日期。然后,您的循环将如下所示:

WHILE(@StartEnd <= @EndDate)
BEGIN
  --processing goes here
  SET @StartEnd = @StartEnd + 1
END
您需要将期间定义存储在另一个表中,以便在需要时检索这些定义并将行输出到临时表中


如果你需要任何更详细的例子,或者如果我搞错了,请告诉我

希望比马丁的书读起来容易一点。我使用了不同的表格和样本数据,希望能推断出正确的信息:

DECLARE @t1 TABLE (periodid INT,periodstart DATE,periodend DATE,quantity INT)
DECLARE @t2 TABLE (periodid INT,periodstart DATE,periodend DATE,solditems INT)

INSERT INTO @t1 VALUES(1,'2010-10-01T00:00:00.000','2010-10-15T00:00:00.000',5)
INSERT INTO @t2 VALUES(14343,'2010-10-05T00:00:00.000','2010-10-06T00:00:00.000',2)

DECLARE @D1 DATE

SELECT @D1 = MIN(P) FROM (SELECT MIN(periodstart) P FROM @t1
                          UNION ALL
                          SELECT MIN(periodstart) FROM @t2) D

DECLARE @D2 DATE

SELECT @D2 = MAX(P) FROM (SELECT MAX(periodend) P FROM @t1
                          UNION ALL
                          SELECT MAX(periodend) FROM @t2) D

;WITH 
L0 AS (SELECT 1 AS c UNION ALL SELECT 1),
L1 AS (SELECT 1 AS c FROM L0 A CROSS JOIN L0 B),
L2 AS (SELECT 1 AS c FROM L1 A CROSS JOIN L1 B),
L3 AS (SELECT 1 AS c FROM L2 A CROSS JOIN L2 B),
L4 AS (SELECT 1 AS c FROM L3 A CROSS JOIN L3 B),
Nums AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS i FROM L4),
Dates AS(SELECT DATEADD(DAY,i-1,@D1) AS D FROM Nums where i <= 1+DATEDIFF(DAY,@D1,@D2))  , 
Stock As (
SELECT D ,t1.quantity - ISNULL(t2.solditems,0) AS itemsinstock
FROM Dates
LEFT OUTER JOIN @t1 t1 ON t1.periodend >= D and t1.periodstart <= D
LEFT OUTER JOIN @t2 t2 ON t2.periodend >= D and t2.periodstart <= D ),
NStock As (
select D,itemsinstock, ROW_NUMBER() over (order by D) - ROW_NUMBER() over (partition by itemsinstock order by D) AS G
from Stock)
SELECT MIN(D) AS periodstart, MAX(D) AS periodend, itemsinstock 
FROM NStock
GROUP BY G, itemsinstock
ORDER BY periodstart
CREATE TABLE [dbo].[Quantity](
    [PeriodStart] [date] NOT NULL,
    [PeriodEnd] [date] NOT NULL,
    [Quantity] [int] NOT NULL
) ON [PRIMARY]

CREATE TABLE [dbo].[SoldItems](
    [PeriodStart] [date] NOT NULL,
    [PeriodEnd] [date] NOT NULL,
    [SoldItems] [int] NOT NULL
) ON [PRIMARY]

INSERT INTO Quantity (PeriodStart,PeriodEnd,Quantity)
SELECT '20100101','20100115',5

INSERT INTO SoldItems (PeriodStart,PeriodEnd,SoldItems)
SELECT '20100105','20100107',2 union all
SELECT '20100106','20100108',1
现在,实际查询是:

;WITH Dates as (
    select PeriodStart as DateVal from SoldItems union select PeriodEnd from SoldItems union select PeriodStart from Quantity union select PeriodEnd from Quantity
), Periods as (
    select d1.DateVal as StartDate, d2.DateVal as EndDate
    from Dates d1 inner join Dates d2 on d1.DateVal < d2.DateVal left join Dates d3 on d1.DateVal < d3.DateVal and d3.DateVal < d2.DateVal where d3.DateVal is null
), QuantitiesSold as (
    select StartDate,EndDate,COALESCE(SUM(si.SoldItems),0) as Quantity
    from Periods p left join SoldItems si on p.StartDate < si.PeriodEnd and si.PeriodStart < p.EndDate
    group by StartDate,EndDate
)
select StartDate,EndDate,q.Quantity - qs.Quantity
from QuantitiesSold qs inner join Quantity q on qs.StartDate < q.PeriodEnd and q.PeriodStart < qs.EndDate
说明:我使用了三种常见的表表达式。第一个日期是收集我们正在讨论的所有日期,从涉及的两个表中。第二个周期从日期CTE中选择连续值。然后,第三个QuantitiesSald在SoldItems表中查找与这些期间重叠的项目,并将它们的总数相加。外部选择中剩下的就是从数量表中存储的总量中减去这些数量

我试图完全理解您的解决方案,并在大量数据上对其进行测试,但您的代码出现以下错误

Msg 102,15级,状态1,第20行

“日期”附近的语法不正确

Msg 102,15级,状态1,第22行

“,”附近的语法不正确

Msg 102,15级,状态1,第25行

“,”附近的语法不正确。

Damien

基于你的解决方案,我还想得到一个整洁的显示库存项目没有重叠的日期。这个解决方案怎么样

CREATE TABLE [dbo].[SoldItems](
    [PeriodStart] [datetime] NOT NULL,
    [PeriodEnd] [datetime] NOT NULL,
    [SoldItems] [int] NOT NULL
) ON [PRIMARY]


INSERT INTO SoldItems (PeriodStart,PeriodEnd,SoldItems)
SELECT '20100105','20100106',2 union all
SELECT '20100105','20100108',3 union all
SELECT '20100115','20100116',1 union all
SELECT '20100101','20100120',10


;WITH Dates as (
    select PeriodStart as DateVal from SoldItems
    union 
    select PeriodEnd from SoldItems 
    union
    select PeriodStart from Quantity
    union
    select PeriodEnd from Quantity

), Periods as (
    select d1.DateVal as StartDate, d2.DateVal  as EndDate
    from Dates d1 
    inner join Dates d2 on d1.DateVal < d2.DateVal 
    left join Dates d3 on d1.DateVal < d3.DateVal and 
    d3.DateVal < d2.DateVal where d3.DateVal is null

), QuantitiesSold as (
    select StartDate,EndDate,SUM(si.SoldItems) as Quantity
    from Periods p left join SoldItems si on p.StartDate < si.PeriodEnd and si.PeriodStart < p.EndDate
    group by StartDate,EndDate
)

select StartDate,EndDate, qs.Quantity
from QuantitiesSold qs
where qs.quantity is not null

如果您使用的是SQL Server,请参阅这篇MSDN文章,了解T-SQL中WHILE循环的详细用法+1,在我将所有日期数据类型更改为DATETIME后对我有效,因为我不在SQL Server 2008上是的-目前我们缺少的是,因为示例数据不是很广泛,是数量表中是否有多行,只需更改为第三个CTE即可,以及这两个表之间是否存在未显示的实际关系,例如,存在多个产品tracked@Martin-我的周期不完全符合运营要求,因为我的周期完全覆盖了范围,即我的第一个周期在5号结束,而不是4号结束。那是因为我习惯于将周期建模为[StartDate,EndDate a半开放式间隔您最好将此作为注释添加到我的答案中,或者将其编辑到您的问题中。对我的答案的注释会提醒我您的更新。仅适用于SQL 2005或更高版本。不确定您使用的是哪个版本,如果查询在批处理中稍后启动,则在with关键字之前需要;I a我使用SQL 2005,并且在with kwd之前已经尝试过;但总是会出现相同的错误。因为我不经常使用with,所以我尝试运行with语句的一些基本示例,但它们都返回相同的错误。??您的解决方案在Quantity表中使用多行时效果很好。但是,日期重叠的问题似乎是c无法使用您的解决方案解决此问题。另一方面,进行必要的更改以将EndDate从第5个调整到第4个,这将导致SoldItems中的单个日期周期被表示为例如2010-05-05-2010-05-05。因此,我相信这对于数据层来说是一个很好的解决方案。
CREATE TABLE [dbo].[SoldItems](
    [PeriodStart] [datetime] NOT NULL,
    [PeriodEnd] [datetime] NOT NULL,
    [SoldItems] [int] NOT NULL
) ON [PRIMARY]


INSERT INTO SoldItems (PeriodStart,PeriodEnd,SoldItems)
SELECT '20100105','20100106',2 union all
SELECT '20100105','20100108',3 union all
SELECT '20100115','20100116',1 union all
SELECT '20100101','20100120',10


;WITH Dates as (
    select PeriodStart as DateVal from SoldItems
    union 
    select PeriodEnd from SoldItems 
    union
    select PeriodStart from Quantity
    union
    select PeriodEnd from Quantity

), Periods as (
    select d1.DateVal as StartDate, d2.DateVal  as EndDate
    from Dates d1 
    inner join Dates d2 on d1.DateVal < d2.DateVal 
    left join Dates d3 on d1.DateVal < d3.DateVal and 
    d3.DateVal < d2.DateVal where d3.DateVal is null

), QuantitiesSold as (
    select StartDate,EndDate,SUM(si.SoldItems) as Quantity
    from Periods p left join SoldItems si on p.StartDate < si.PeriodEnd and si.PeriodStart < p.EndDate
    group by StartDate,EndDate
)

select StartDate,EndDate, qs.Quantity
from QuantitiesSold qs
where qs.quantity is not null