我有一张只显示工作日值的表。它从仅在工作日导入的文件中获取这些信息。我还需要在周末(或节假日)中添加先前已知值的值。当我需要在MS Access中使用此question时,我曾问过它。我现在正在将该数据库移至SQL Server。
如果您想在Access中查看对我有用的内容,欢迎您查看link。
我尝试使用以下方法使MS Access SQL适应SQL Server:
SELECT a1.IDNbr, a1.Balance, CONVERT(int, DAY(a1.BalDate)) + 3
FROM tblID a1 INNER JOIN tblID a2 ON (CONVERT(int, DAY(a1.BalDate)) + 4 = a2.BalDate) AND (a1.IDNbr = a2.IDNbr)
WHERE NOT EXISTS (
SELECT *
FROM tblID a3
WHERE a3.IDNbr = a1.IDNbr AND a3.BalDate = CONVERT(int, DAY(a1.BalDate)) + 3) AND (DATEPART(W, a1.BalDate) = 6
);
但是,出现错误:
第206级2状态4行的消息
操作符类型冲突:日期与int不兼容
问题::如何获取此查询(该查询将变为INSERT语句),以显示数据中的所有缺失日期,并将最后一个已知日期的值分配给失踪的日子?
我拥有的数据(从星期五开始):
+-------------------------------------+
|ID | IDNbr | Balance | BalDate |
+-------------------------------------+
|001| 91 | 529 | 1/5/2018 |
|002| 87 | 654 | 1/5/2018 |
|003| 45 | 258 | 1/5/2018 |
|004| 91 | 611 | 1/8/2018 |
|005| 87 | 753 | 1/8/2018 |
|006| 45 | 357 | 1/8/2018 |
|...| .. | ... | ........ |
+-------------------------------------+
'BalDate then skips past 1/6/2018 and 1/7/2018 to 1/8/2018
我需要的数据:
+-------------------------------------+
|ID | IDNbr | Balance | BalDate |
+-------------------------------------+
|001| 91 | 529 | 1/5/2018 |
|002| 87 | 654 | 1/5/2018 |
|003| 45 | 258 | 1/5/2018 |
|004| 91 | 529 | 1/6/2018 |
|005| 87 | 654 | 1/6/2018 |
|006| 45 | 258 | 1/6/2018 |
|007| 91 | 529 | 1/7/2018 |
|008| 87 | 654 | 1/7/2018 |
|009| 45 | 258 | 1/7/2018 |
|010| 91 | 611 | 1/8/2018 |
|011| 87 | 753 | 1/8/2018 |
|012| 45 | 357 | 1/8/2018 |
|...| .. | ... | ........ |
+-------------------------------------+
'I'm needing it to add the Saturday(1/6/2018) and Sunday(1/7/2018) before continuing on to 1/8/2018
任何帮助将不胜感激。预先谢谢你!
如果有不赞成票,请您解释为什么要不赞成票,以便我纠正!
答案 0 :(得分:2)
好的,您将需要Bernd的答案中的CalTable()函数。我们将使用它来创建setlocal EnableExtensions
for %%I in ("Game Files\*.BNK") do call :ProcessBNK "%%I"
exit /b
:ProcessBNK
set _targetDir="%~n1"
md %_targetDir% 2>nul
Tools\bnkextr.exe %1
move *.wav Tools\Decoding
for %%I in (Tools\Decoding\*.WAV) do call :ProcessWAV "%%I"
for %%I in (Tools\Decoding\*.OGG) do Tools\revorb.exe "%%I"
move Tools\Decoding\*.OGG %_targetDir%
move %1 %_targetDir%
exit /b
:ProcessWAV
Tools\ww2ogg.exe %1 --pcb Tools\packed_codebooks_aoTuV_603.bin
del %1
exit /b
中MIN(BalDate)
和MAX(BalDate)
之间的所有日历日期的列表。我们还将使用tblID
值列表来CROSS JOIN
,我认为这是DISTINCT IDNbr
的PK。
让我们创建一些示例数据。
tblID
接下来,我们将在遗失的日子中将新记录插入#tblID中。这里的神奇之处在于CREATE TABLE #tblID (ID VARCHAR(3), IDNbr INT, Balance INT, BalDate DATE)
INSERT INTO #tblID
(
ID
,IDNbr
,Balance
,BalDate
)
VALUES
('001',91,529,'1/5/2018'),
('002',87,654,'1/5/2018'),
('003',45,258,'1/5/2018'),
('004',91,611,'1/8/2018'),
('005',87,753,'1/8/2018'),
('006',45,357,'1/8/2018')
函数,该函数可以查看上一行的数据。我们根据缺失日期与数据的最后日期之间的差值为其提供一个偏移值的表达式。
LAG()
在这一点上,如果我们不关心;WITH IDs AS
(
SELECT DISTINCT
IDNbr
FROM #tblID
)
,IDDates AS
(
SELECT
BalDate = c.[Date]
,i.IDNbr
FROM [CalTable]((SELECT MIN(BalDate) FROM #tblID), (SELECT MAX(BalDate) FROM #tblID)) c
CROSS APPLY IDs i
)
,FullResults AS
(
SELECT
i.BalDate
,i.IDNbr
,Balance = CASE WHEN t.Balance IS NOT NULL THEN t.Balance
ELSE LAG(t.Balance,
DATEDIFF(
DAY
,(SELECT MAX(t1.BalDate) FROM #tblID t1 WHERE t1.IDNbr = i.IDNbr AND t1.BalDate <= i.BalDate GROUP BY t1.IDNbr)
,i.BalDate
)
) OVER (PARTITION BY i.IDNbr ORDER BY i.BalDate ASC)
END
FROM IDDates i
LEFT JOIN #tblID t ON t.BalDate = i.BalDate AND t.IDNbr = i.IDNbr
)
INSERT INTO #tblID
(
IDNbr
,Balance
,BalDate
)
SELECT
f.IDNbr
,f.Balance
,f.BalDate
FROM FullResults f
LEFT JOIN #tblID t ON t.IDNbr = f.IDNbr AND t.BalDate = f.BalDate
WHERE t.IDNbr IS NULL
字段(该字段似乎是行号的3个字符的字符串表示形式),那就很好了。但是,尽管我认为以这种方式使用字符串不是一个好习惯,但我也不是对我不了解的其他人的业务需求发表评论的人。
因此,假设我们必须更新ID
字段以匹配预期的输出。我们可以这样:
ID
现在,如果您查询更新的表,您将获得以下信息:
;WITH IDUpdate AS
(
SELECT
ID = RIGHT('000' + CAST(ROW_NUMBER() OVER (ORDER BY BalDate ASC, IDNbr DESC) AS VARCHAR), 3)
,t.IDNbr
,t.Balance
,t.BalDate
FROM #tblID t
)
UPDATE t
SET t.ID = i.ID
FROM #tblID t
INNER JOIN IDUpdate i ON i.IDNbr = t.IDNbr AND i.BalDate = t.BalDate
输出:
SELECT
ID
,IDNbr
,Balance
,BalDate
FROM #tblID
ORDER BY BalDate ASC, IDNbr DESC
答案 1 :(得分:1)
以下是链接函数的示例:
create FUNCTION [dbo].[CalTable]
(
@startDate date,
@endDate date
)
RETURNS
@calender TABLE
(
[Date] date not null primary key CLUSTERED,
isMondayToFriday bit not null
)
AS
BEGIN
declare @currentday date = @startDate;
declare @isMondayToFriday bit;
while (@currentday<=@endDate)
begin
-- respect DATEFIRST depending on language settings
if (DATEPART(dw, @currentday)+@@DATEFIRST-2)%7+1>5
set @isMondayToFriday = 0
else
set @isMondayToFriday = 1
insert into @calender values (@currentday, @isMondayToFriday);
set @currentday = DATEADD(D, 1, @currentday);
end
RETURN
END
GO
select * from [CalTable]({d'2018-01-01'}, {d'2018-02-03'});
使用它来查找差距。