因此,我有一个line_items
表与一个orders
表链接。显然,一个order
可以有多个line_item
。
line_item
除其他事项外还具有item_status
。所有item_status
都列在一个自然称为item_statuses
的表中。该表中有一个stage
列,它指示状态的线性性质。因此,item_status
中的proofing
具有stage
中的20
,因为它在生产管道中的出现要早于printing
,即{{ 1}}。 60
是shipping
,依此类推。它指示生产管道中80
的状态。
因此,我很容易查看给定line_item
有多少line_item
个并按其order
进行分组。一个item_status
可能有2个order
在line_item
部门中,但是有1个项目仍然是shipping
。到目前为止有道理吗?
要实现我的最终目标,我需要确定printing
的“状态”。为此,我决定将order
的“状态”与其所有order
的最早 item_status
相同。 (我将引号用在line_item
的“状态”中,因为它从未真正存储在任何地方,只是即时计算出来。一个View可以帮助存储它。)
因此,如果order
具有3个order
,其中line_item
个分别为item_status
,printing
和shipping
,则shipping
的总体“状态”应为order
,因为它的printing
仍然停留在较早的line_item
中。 (因为item_status
表中printing
的{{1}}数比stage
小。)
我想创建一个视图,该视图将为我提供item_statuses
表中所有所有记录的shipping
号及其“状态”。
最终,我需要通过它们的order
(也是orders
表中的一列)来统计所有order
的数量,但按其“状态”细分。 (因此,例如,给定的ship_date
将有78个orders
,分别是ship_date
,139个order
和43个shipping
。我认为创建视图我提到这将是实现该目标的垫脚石。)
到目前为止,这是我所能想到的:
printing
这很丑。这很复杂。它所做的就是为单个硬编码的proofing
获取“最早的” SELECT
orders.ship_date_id,
orders.id,
item_statuses.id
FROM item_statuses
JOIN line_items
ON item_statuses.id = line_items.item_status_id
JOIN orders
ON line_items.order_id = orders.id
WHERE item_statuses.stage = (
SELECT MIN(item_statuses.stage)
FROM item_statuses
JOIN (
SELECT line_items.item_status_id
FROM line_items
JOIN orders
ON line_items.order_id = orders.id
WHERE orders.id = '521079'
) AS x
ON x.item_status_id = item_statuses.id
)
,然后仅显示具有该“状态”的订单。我需要这样做才能向我显示所有订单及其关联的“状态”。
所有这些只是让我成为实现目标的一部分。正如我之前提到的,我最终将需要它来获取所有订单的计数,并按日期(在一周范围内)分开,并查看当天每个“状态”中有多少订单。
最糟糕的是,我知道这应该是可能的。我什至看不见它甚至有一个优雅的解决方案。因此,我来这里是不得已而为之。
答案 0 :(得分:2)
(实际上)比您想象的要简单。让我们来建立它。
首先,让我们开始介绍所有项目:
SELECT Line_Items.order_id, Item_Statuses.stage
FROM Line_Items
JOIN Item_Statuses
ON Item_Statuses.id = Line_Items.item_status_id
这会(看起来)像这样:
1 | 20
1 | 39
2 | 50
好吧,现在,由于每个订单有多行,所以我们需要每个订单的最小阶段。简单汇总:
SELECT Line_Items.order_id, MIN(Item_Status.stage) AS stage
FROM Line_Items
JOIN Item_Statuses
ON Item_Statuses.id = Line_Items.item_status_id
GROUP BY Line_Items.order_id
哪个会产生:
1 | 20
2 | 50
现在,由于您需要交货日期,因此我们需要将Orders
表联接到上一个查询的整个结果集中。这意味着我们需要一个子查询:
SELECT Orders.id, Orders.ship_date_id,
Order_Status.stage,
FROM Orders
LEFT JOIN (SELECT Line_Items.order_id, MIN(Item_Status.stage) AS stage
FROM Line_Items
JOIN Item_Statuses
ON Item_Statuses.id = Line_Items.item_status_id
GROUP BY Line_Items.order_id) AS Order_Status
ON Order_Status.order_id = Orders.id
哪个会产生:
1 | "2015-01-01" | 20
2 | "2015-01-04" | 50
3 | "2015-01-05" | (null) -- you might have orders without line items!
尚不清楚是否要/阶段有文字说明。如果是这样,您还需要再次加入状态表:
SELECT Orders.id, Orders.ship_date_id,
Item_Statuses.stage,
FROM Orders
LEFT JOIN (SELECT Line_Items.order_id, MIN(Item_Status.stage) AS stage
FROM Line_Items
JOIN Item_Statuses
ON Item_Statuses.id = Line_Items.item_status_id
GROUP BY Line_Items.order_id) AS Order_Status
ON Order_Status.order_id = Orders.id
JOIN Item_Statuses
ON Item_Status.stage = Order_Status.stage
(此特定版本假定stage
是一个唯一值-如果不是,则还有其他问题)
1 | "2015-01-01" | 'Printing'
2 | "2015-01-04" | 'Proofing'
3 | "2015-01-05" | (null) -- you might have orders without line items!
如何获取订单数?
好吧,获取特定日期的订单数很容易:
SELECT Orders.ship_date_id, COUNT(*) as orders
FROM Orders
GROUP By Orders.ship_date_id
"2015-01-01" | 1
"2015-01-04" | 400
"2015-04-05" | 33
然后您可以将两个查询大部分合并在一起:
SELECT Orders.ship_date_id, Order_Status.stage,
COUNT(*) AS orders
FROM Orders
LEFT JOIN (SELECT Line_Items.order_id, MIN(Item_Status.stage) AS stage
FROM Line_Items
JOIN Item_Statuses
ON Item_Statuses.id = Line_Items.item_status_id
GROUP BY Line_Items.order_id) AS Order_Status
ON Order_Status.order_id = Orders.id
GROUP BY Orders.ship_date_id, Order_Status.stage
类似这样:
"2015-01-01" | 20 | 1
"2015-01-04" | 30 | 200
"2015-01-04" | 40 | 200
"2015-04-05" | 40 | 2
"2015-04-05" | 20 | 30
"2015-04-05" | (null) | 1
(如果此时需要阶段名称,最好将整个查询推送到子查询中,然后再次为该名称联接,因为否则必须将名称添加为分组中的额外列。保留为读者的练习。)
如果您想限制日期范围,可以将其包括在视图中,但是我可能会保留它,而只在查询视图本身时添加WHERE
子句:
SELECT ship_date_id, stage, orders
FROM Orders_Per_Day
WHERE ship_date_id >= :start
AND ship_date_id < :end
精明的读者会注意到日期范围中存在差距。不管是否在视图中,加入日历表(获取缺少日期的推荐方法)也留给读者练习。
答案 1 :(得分:0)
您的问题并不复杂,只要您的帖子很长。 :)
我认为您要寻找的是这个
SELECT
tbl.ship_date_id,
tbl.order_id,
tbl.item_status_id order_status
FROM
(
SELECT
orders.ship_date_id,
orders.id order_id,
item_statuses.id item_status_id,
ROW_NUMBER()OVER(PARTITION BY orders.id ORDER BY item_statuses.id ASC) rn
FROM orders
JOIN line_items ON line_items.order_id = orders.id
JOIN item_statuses ON item_statuses.id = line_items.item_status_id
) tbl
WHERE tbl.rn = 1
那么您应该能够根据ship_date_id`s
进行统计这应该在item_statuses.id
是随过程进展而递增的数字的假设下进行(例如printing
的ID为3,而shipping
的ID为4`,等等)>
说明:
ROW_NUMBER函数将根据item_statuses.id
按每个订单(1,2,3,...)对商品进行排序,我们只需要在流程的最早步骤中为该商品排一行。>