SQL Server 查询以计算每日“持仓”未结订单
Posted
技术标签:
【中文标题】SQL Server 查询以计算每日“持仓”未结订单【英文标题】:SQL Server query to calculate daily “carrying” open orders 【发布时间】:2017-08-12 11:50:19 【问题描述】:我在整个网站上进行了搜索,但似乎找不到适合我特定问题的解决方案。有许多接近我正在寻找的东西,但还不足以(至少对于我的编码能力)来建立联系。
我有一个相对简单的表,其中有:
Order_Number Order_Date Fulfilled_Date还有许多其他字段,但它们与此问题无关。
我需要创建一份报告,显示(按每日细分)在 30 天内“未完成”的订单数量。显然,“空”值表示订单当前未履行,但我真的很纠结如何解决每天有多少未履行订单的问题。
在某些情况下,订单可能在几个月前下达,但仍未完成(可能是由于延期交货状态),因此我需要回顾几乎从开始时的餐桌时间。
另外,对于这个问题,请考虑我没有可用的“日期”或“日期”表,因此无法制作。我可以在临时表中构建一个,但没有永久性的。另外,我只需要担心从“今天”开始的 30 天(getdate()-30)
样本数据:
create table #orders
(
order_number varchar(25),
order_date datetime,
fulfilled_date datetime
)
insert into #orders (order_number, order_date, fulfilled_date)
values ('HK02411580-92880', '2/22/17 23:06', '2/27/17 23:11'),
('HK02411580-93259', '2/22/17 11:22', '2/22/17 16:27'),
('HK02411580-93760', '2/22/17 23:46', '2/22/17 23:51'),
('HK02411580-94122', '2/23/17 0:06', '2/25/17 0:16'),
('HK02411580-94845', '2/23/17 0:42', '2/26/17 0:42'),
('HK02411580-94847', '2/23/17 0:42', '2/23/17 0:42'),
('HK02411580-94952', '2/23/17 0:46', '2/23/17 0:51'),
('BS63719405-53119', '2/24/17 23:44', '2/25/17 23:44'),
('BS63719405-53231', '2/24/17 23:48', '2/28/17 23:49'),
('BS63719405-53336', '2/24/17 23:54', '2/24/17 23:54'),
('BS63719405-53546', '2/25/17 0:04', '2/27/17 0:04'),
('BS63719405-53672', '2/25/17 0:09', '2/28/17 0:09'),
('UT40057640-11866', '2/26/17 23:06', '3/1/17 23:11'),
('UT40057640-11910', '2/26/17 23:07', '3/5/17 23:17'),
('UT40057640-13217', '2/27/17 0:11', '2/27/17 0:16'),
('UT40057640-13829', '2/27/17 0:41', '2/27/17 0:41'),
('UT40057640-93881', '3/1/17 13:28', '3/1/17 13:29'),
('UT40057640-94117', '3/1/17 13:38', '3/5/17 13:39'),
('SC79933239-74181', '3/3/17 22:02', '3/4/17 22:08'),
('SC79933239-76349', '3/3/17 23:32', '3/3/17 23:37'),
('SC79933239-76716', '3/3/17 23:51', '3/3/17 23:56'),
('SC79933239-77351', '3/4/17 0:18', '3/5/17 0:19'),
('SC79933239-77899', '3/4/17 0:41', '3/6/17 0:41'),
('SC79933239-77900', '3/4/17 0:41', '3/4/17 0:41'),
('FM76423870-59430', '3/6/17 9:54', '3/10/17 9:54'),
('FM76423870-59552', '3/6/17 9:59', '3/11/17 9:59'),
('FM76423870-59676', '3/6/17 10:03', '3/9/17 10:04'),
('FM76423870-59798', '3/6/17 10:09', '3/6/17 10:09'),
('IE68709323-78813', '3/20/17 7:01', '3/20/17 7:53'),
('IE68709323-78905', '3/20/17 7:09', '3/20/17 7:53'),
('RC45792362-15830', '3/20/17 7:59', NULL),
('RC45792362-15831', '3/20/17 7:59', NULL),
('RC45792362-16653', '3/20/17 8:39', NULL),
('RC45792362-24157', '3/20/17 14:52', NULL),
('RC45792362-24163', '3/20/17 14:52', '3/20/17 14:57'),
('RC45792362-24223', '3/20/17 14:54', NULL),
('RC45792362-24327', '3/20/17 14:56', '3/20/17 14:59'),
('RC45792362-24267', '3/20/17 14:57', NULL),
('RC45792362-27486', '3/20/17 17:32', NULL),
('RC45792362-27607', '3/20/17 17:36', '3/20/17 17:39');
所需的输出将是(例如):
Date Carry Over Orders
--------- -----------------
2/22/2017 1 (3 orders...2 fulfilled and one left over or "carried over")
2/23/2017 3 (2 orders fulfilled that day, but 2 additional carried over)
2/24/2017 5 (1 order fulfilled that day, but 2 additional carried over)
2/25/2017 5 (2 orders fulfilled from prior dates but 2 new orders carried over)
Etc...
我希望我解释得对...当我开始走这条路时似乎很简单,但它只是没有在大脑中点击正确...
非常感谢任何帮助。
服务器版本:SQL Server 2008
还要添加一项:对于没有订单的日期,我仍然需要考虑它们...我希望必须根据开始日期编写某种临时日期表并向后工作 30 天。 .除非有更好的方法。
澄清:在结果集中,“结转订单”本质上是在该特定日期内未履行的订单的累计总数。
逻辑澄清:
在 22 日,总共有 3 个订单...其中 2 个已完成(如果您愿意,也可以发货),1 个未完成。这使得 1 个未完成的订单进入 23 日。
23 日总共有 4 个订单。其中 2 条当天实现,2 条没有实现。前一天的订单仍未完成,因此“结转”订单总数达到 3 个。
24 日我们还有另外 3 个订单。 1 那天完成了,2 没有完成。总结转现在是 5
在 25 日,我们有 2 个当天未完成的新订单,但之前有 2 个订单(一个来自 23 日,一个来自 24 日)。 Carr-over 订单(或未完成的订单)总数保持在 5 个。
希望这能帮助更多
为了帮助解决这个问题,我创建了一个 rextester(因为 sqlfiddle 似乎坏了) rextester sandbox
【问题讨论】:
第二列的1、3、5、5分别代表什么? 抱歉...这些将是当天未完成的订单总数。 为什么 2/22/2017 没有完成订单? 需要“未完成”的订单。 2/22(开始)有 2 个订单已完成,但 1 个订单未完成,因此将被视为结转 您可能想澄清您所说的结转订单的含义。 【参考方案1】:这应该会给你想要的输出。此查询假定您有一个不同的日期列表来查询。
您最麻烦的部分,即结转部分,使用了引用两个数据集的FROM
语句。这与JOIN
不同,它是通过引用两个表并用,
分隔它们来完成的。这将反过来创建一个查询,其中dates_table
中的每个日期都从orders
表中分配了整个数据集。为了确定结转,使用WHERE
语句过滤复制的订单表,并使用GROUP BY
计算每个过滤后的订单。之后使用LEFT JOIN
将结果按日期拉到date_table
。如果您需要更多解释,请随时发表评论。
SQL with Dates Table这个表在下面的查询中被命名为dates_table
SELECT
dates.date,
iif(carry_over.count IS NULL, 0, carry_over.count) AS carry_over,
iif(fulfilled.count IS NULL, 0, fulfilled.count) AS fulfilled,
iif(not_fulfilled.count IS NULL, 0, not_fulfilled.count) AS not_fulfilled
FROM dates_table AS dates
/* Fulfilled that day */
LEFT JOIN
(
SELECT
dateadd(d, datediff(d,0, fulfilled_date), 0) AS date,
COUNT(dateadd(d, datediff(d,0, fulfilled_date), 0)) AS count
FROM orders
GROUP BY dateadd(d, datediff(d,0, fulfilled_date), 0)
) AS fulfilled
ON dates.date = fulfilled.date
/* Not Fulfilled that day */
LEFT JOIN
(
SELECT
dateadd(d, datediff(d,0, order_date), 0) AS date,
COUNT(dateadd(d, datediff(d,0, order_date), 0)) AS count
FROM orders
WHERE (dateadd(d, datediff(d,0, order_date), 0) <> dateadd(d, datediff(d,0, fulfilled_date), 0)) OR fulfilled_date IS NULL
GROUP BY dateadd(d, datediff(d,0, order_date), 0)
) AS not_fulfilled
ON dates.date = not_fulfilled.date
/* Carry Over */
LEFT JOIN
(
SELECT
full_data.date,
COUNT(full_data.order_date) AS count
FROM
(
SELECT
dates.date AS date,
order_dates.order_date AS order_date,
order_dates.fulfilled_date AS fulfilled_date
FROM dates_table AS dates,
/* Allocate all dates to key of dates, filter out what is relevant in where */
(
SELECT
dateadd(d, datediff(d,0, order_date), 0) AS order_date,
iif(fulfilled_date IS NULL, NULL, dateadd(d, datediff(d,0, fulfilled_date), 0)) AS fulfilled_date
FROM orders
) AS order_dates
) AS full_data
/* Determines what is carry over */
WHERE (full_data.date < full_data.fulfilled_date OR full_data.fulfilled_date IS NULL) AND full_data.date >= full_data.order_date
GROUP BY full_data.date
) AS carry_over
ON dates.date = carry_over.date
rextester
编辑:为最终查询添加了字段名称,因为它们之前都被标记为 count
编辑:假设您有一个日期表和订单表的#,添加了另一个查询
编辑:删除了没有 date_table 的查询,现在在 order_date 上完成了carry_over 的计数,因为不计算空值,对于已完成的那一天数字现在提取fulfilled_date 而不是 order_date
【讨论】:
这绝对给了我数据..我需要使用日期表,因为我确实需要显示连续的日期......所以如果某一天没有订单,会有仍然是“待定”订单或“结转”订单...您对如何整合该部分有建议吗? 假设您有一个日期表,我将发布另一个 sql 查询。 @Buckwheattb 我已经更新了我的答案。这就是你要找的东西吗? 我也可以像你那样使用我的空间,这样占用的空间会少很多 @DavidLee 这很接近,但是当查询命中没有活动的日期(订单表中缺少日期范围)时,它似乎分开了......我制作了一个从 2 开始的日期表/20 到 3/21 作为测试。答案集在早期看起来不错,但是一旦进入无订单时期(特别是 3/6 到 3/20 时期),结果就消失了……另一件事……在“未完成”天”部分,我进行了更改以适应“NULL”履行日期...“isnull(dateadd(d,datediff(d,0,fulfilled_date),0),'1/1/2050')”这有意义吗?以上是关于SQL Server 查询以计算每日“持仓”未结订单的主要内容,如果未能解决你的问题,请参考以下文章
用于 Google BigQuery 的 SQL 查询以计算会话和浏览量