1

カーソル(FETCH)の使用を避けて、この問題を解決したいと思います。

ここで問題が発生します...

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

カーソルを使用せずに、またはピリオドの代わりに単一の日付を使用せずに、この問題を解決することは不可能に思えます。

助けていただければ幸いです。

ありがとう

4

5 に答える 5

2
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
于 2010-10-22T12:57:47.563 に答える
1

うまくいけば、Martin のものよりも少し読みやすくなります。うまくいけば、正しい情報を推測して、さまざまなテーブルとサンプル データを使用しました。

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

結果は次のとおりです。

StartDate   EndDate (No column name)
2010-01-01  2010-01-05  5
2010-01-05  2010-01-06  3
2010-01-06  2010-01-07  2
2010-01-07  2010-01-08  4
2010-01-08  2010-01-15  5

説明: 3 つの共通テーブル式を使用しています。最初の (Dates) は、関連する 2 つのテーブルから、ここで話しているすべての日付を収集します。2 番目 (期間) は、日付 CTE から連続する値を選択します。そして 3 番目 (QuantitiesSold) は、SoldItems テーブルでこれらの期間と重複するアイテムを検索し、それらの合計を合計します。外側の選択に残っているのは、数量テーブルに格納されている合計数量からこれらの数量を差し引くことだけです

于 2010-10-22T13:19:44.337 に答える
0

ジョン、あなたができることはWHILEループです。ループの前に2つの変数を宣言して初期化します。1つは開始日で、もう1つは終了日です。ループは次のようになります。

WHILE(@StartEnd <= @EndDate)
BEGIN
  --processing goes here
  SET @StartEnd = @StartEnd + 1
END

期間定義を別のテーブルに格納する必要があるため、必要に応じてそれらを取得して行を一時テーブルに出力できます。

より詳細な例が必要な場合、またはスティックの端が間違っている場合はお知らせください。

于 2010-10-22T12:51:08.240 に答える
0

ダミアン

あなたのソリューションに基づいて、日付が重ならないように StockItems をきちんと表示したいとも思っていました。この解決策はどうですか?

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
于 2010-10-28T10:31:52.163 に答える
0

ダミアン

ソリューションを完全に理解し、大規模なデータでテストしようとしていますが、コードに対して次のエラーが表示されます。

メッセージ 102、レベル 15、状態 1、行 20

「日付」付近の構文が正しくありません。

メッセージ 102、レベル 15、状態 1、行 22

「,」付近の構文が正しくありません。

メッセージ 102、レベル 15、状態 1、行 25

「,」付近の構文が正しくありません。

于 2010-10-26T07:16:51.283 に答える