2015-02-10 76 views
0

在此先感谢您提供的任何帮助。到目前为止,我在这里或其他地方的搜索中找不到像这样的任何内容,但我敢打赌更多的是因为我不知道描述问题/问题的标准方式。TSQL子查询正在混淆群由

我正在建立一个查找代码从数据驻留在两个不同的表。我们有菜单项可以与一个或多个选项相关联。在这种情况下,我们正在处理与一种肉类(选择)和一种米饭(在同一选择表中找到的另一种选择)一起供应的咖喱(物品)。完整的PLU是与2个选择类别中的每一个的选择级SKU级联的项目​​级SKU。一个完整的PLU的一个例子是:

'CuMaBfWh' 

其中“CUMA”是项目水平SKU和“详细的展望”和“瓦”分别SKU的选择级别。我能够在外部查询中使用子查询(不喜欢它)来构建PLU。问题是这种方法不允许我正确分组数据。样本表,查询,有问题的输出和正确的输出。

这些表中给定的采样数据:

订票

 
i_ticket_id 

    3 

TicketItem

 
i_ticket_item_id i_ticket_id i_menu_item_id dt_when 

     1     3   1  '02/08/2015 16:42:00' 
     2     3   1  '02/08/2015 16:42:00' 
     3     3   1  '02/08/2015 16:42:00' 
     4     3   1  '02/08/2015 16:42:00' 

菜单项

 
i_menu_item_id  s_mi_sku  

    1    'CuMa' 

ChoiceItem

 
i_choice_item_id  i_ticket_item_id i_choice_id 

    1     1     2 
    2     1     8 
    3     2     1 
    4     2     8 
    5     3     4 
    6     4     9 

选择

 
i_choice_id  s_choice_sku 

    1   'Ch' 
    2   'Bf' 
    3   'Po' 
    4   'To' 
    5   'St' 
    6   'Ve' 
    7   'Sh$' 
    8   'Wh' 
    9   'Br'  
    10   'Fr$' 
    11   'Nr' 

正确的输出将如下所示:

 
Date  PLU  Qty Amount 
----  ---  --- ------ 
02/08/2015 CuMaBfWh 2 19.00 
02/08/2015 CuMaChWh 1  9.50 
02/08/2015 CuMaToBr 1  9.50 

我有问题的查询:

SELECT CONVERT(VARCHAR(10), ti.dt_when, 101) [Date], 
     -- Start building the PLU with the sku from the item level 
     mi.s_mi_sku 
     -- Continue building the PLU by adding on the choice sku from the chosen meat 
    + (SELECT TOP(1) c1.s_choice_sku 
    FROM Choices c1 
     INNER JOIN 
       ChoiceItem ci1 ON ci1.i_choice_id = c1.i_choice_id AND c1.s_choice_sku IN ('Ch', 'Bf', 'Po', 'To', 'St', 'Ve', 'Sh$') 
     WHERE ci1.i_ticket_item_id = ti.i_ticket_item_id) 
     -- Complete the PLU by adding on the choice sku from the chosen rice 
    + (SELECT TOP(1) c2.s_choice_sku 
     FROM Choices c2 
      INNER JOIN 
       ChoiceItem ci2 ON ci2.i_choice_id = c2.i_choice_id AND c2.s_choice_sku IN ('Wh', 'Br', 'Fr$', 'Nr') 
     WHERE ci2.i_ticket_item_id = ti.i_ticket_item_id) [PLU], 
    SUM(ti.f_ticketitem_share_qty) [Qty], 
    SUM(ti.c_ticketitem_net_price) [Amount] 
FROM Ticket t 
    INNER JOIN 
TicketItem ti on t.i_ticket_id = ti.i_ticket_id 
    INNER JOIN 
MenuItem mi on ti.i_menu_item_id = mi.i_menu_item_id 
WHERE ti.dt_when >= '2/8/2015 04:00:00' and ti.dt_when <= '2/9/2015 03:59:00' and mi.s_mi_sku = 'CuMa' 
GROUP BY mi.s_mi_sku, ti.dt_when, ti.i_ticket_item_id 

产生以下问题的输出:

 
Date  PLU  Qty Amount 
----  ---  --- ------ 
02/08/2015 CuMaBfWh 1 9.50 
02/08/2015 CuMaChWh 1 9.50 
02/08/2015 CuMaToBr 1 9.50 
02/08/2015 CuMaBfWh 1 9.50 

我一直认为,这是有必要包括ti.i_ticket_item_id结果在'GROUP BY'条款中,但我无法找到另一种方式来做到这一点。

有什么想法?所有建设性的意见/批评是赞赏!

谢谢, 大卫

+0

你能改变数据库设计吗?如果是,那么你的问题和解决方案变得更简单了? – 2015-02-10 05:12:00

+0

不幸的是我无法修改设计。这是第三方POS系统的后端。我正在提取销售数据以导入库存/菜单成本计划。 – David 2015-02-10 05:19:20

+0

在ticket item表中,无论ticket_id是什么,ticket_item_id在表中都是唯一的吗?或者每个ticket_id都是唯一的ticket_item_id? – 2015-02-10 05:29:10

回答

0

我不明白怎么ti.f_ticketitem_share_qty适合的东西,所以我刚才说了一些聚合,因此预期由工作组。还要注意,您提供的数据不包括2位客户在同一订单上订购相同商品的情况,所以我添加了数据以便分组显示相关内容。

declare @Ticket table (i_ticket_id int) 
insert into @Ticket values(3) 

declare @TicketItem table (i_ticket_item_id int, i_ticket_id int, i_menu_item_id int, dt_when datetime) 
insert into @TicketItem 
values 
    (1,3,1,'02/08/2015 16:42:00'), 
    (2,3,1,'02/08/2015 16:42:00'), 
    (3,3,1,'02/08/2015 16:42:00'), 
    (4,3,1,'02/08/2015 16:42:00'), 
    (5,3,1,'02/08/2015 16:42:00') 

declare @MenuItem table (i_menu_item_id int, s_mi_sku varchar(10)) 
insert into @MenuItem values (1,'CuMa') 


declare @ChoiceItem table (i_choice_item_id int, i_ticket_item_id int, i_choice_id int) 
insert into @ChoiceItem 
values 
    (1,1,2), 
    (2,1,8), 
    (3,2,1), 
    (4,2,8), 
    (5,3,4), 
    (6,4,9), 
    (7,5,2), 
    (8,5,8) 

declare @Choices table (i_choice_id int, s_choice_sku varchar(3)) 
insert into @Choices 
values 
    (1,'Ch'), 
    (2,'Bf'), 
    (3,'Po'), 
    (4,'To'), 
    (5,'St'), 
    (6,'Ve'), 
    (7,'Sh$'), 
    (8,'Wh'), 
    (9,'Br'), 
    (10,'Fr$'), 
    (11,'Nr') 

select 
    ti.dt_when, 
    isnull(m.s_mi_sku,'') + isnull(C1.s_choice_sku,'') + isnull(C2.s_choice_sku,'') as PLU, 
    count(t.i_ticket_id) as QTY 
from 
    @Ticket t 
    inner join @TicketItem ti 
     on t.i_ticket_id = ti.i_ticket_id 
    inner join @MenuItem m 
     on m.i_menu_item_id = ti.i_menu_item_id 
    left join 
      (select 
       c1.i_ticket_item_id, 
       sum(case when c1.i_choice_id <=7 
         then c1.i_choice_id 
        else 0 end) c1, 
       sum(case when c1.i_choice_id >=8 
         then c1.i_choice_id 
        else 0 end) c2 
      from 
       @ChoiceItem c1 
      group by c1.i_ticket_item_id 
      ) c 
     on c.i_ticket_item_id = ti.i_ticket_item_id 
    left join @Choices C1 
     on C1.i_choice_id = c.c1 
    left join @Choices C2 
     on C2.i_choice_id = c.c2 
where 
    ti.dt_when between '2/8/2015 04:00:00' and '2/9/2015 03:59:00' 
    and m.i_menu_item_id = 1 
group by 
    ti.dt_when, 
    m.s_mi_sku, 
    C1.s_choice_sku, 
    C2.s_choice_sku 
+0

谢谢@GB。我正在审查您提出的解决方案。有一些问题,因为它似乎取决于我的原始示例中提供的预定义顺序中存储的选择sku。我没有提及选择不是按照特定顺序进行的,因此,在定义第一个左连接的子查询中使用定位将不起作用。我将尝试修改以使用s_choice_sku字符串和IN,而不是Choices表中选择的位置。 – David 2015-02-10 15:28:23

+0

没问题。是的,你需要改变它,不仅是为了sku场景,而且也是为了其他人 - 显然我不知道你的情况的复杂性。你的问题是你无法正确分组......你现在能够根据我的解决方案做到这一点吗? – 2015-02-10 18:57:04

+0

根据我提供的示例数据,您的解决方案绝对可行。从这个角度来看,对我来说这是公平的答案。我想我也会发布一旦我拥有了一些东西,最终会终止。 – David 2015-02-11 17:17:53