TSQL子查询正在混淆分组

时间:2015-02-10 04:44:02

标签: sql-server tsql group-by subquery

提前感谢您提供的任何帮助。到目前为止,我在这里或其他地方的搜索中找不到这样的内容,但是我更多地打赌它因为我不知道描述问题的标准方式/问题

我根据位于两个不同表中的数据构建查找代码。我们有菜单项,可以与一个或多个选项相关联。在这种情况下,我们正在处理咖喱(项目),这些咖喱配有一种肉类(选择)和一种米饭(在同一选择表中找到另一种选择)。完整的PLU是与2个选择类别中的每一个的选择级别SKU连接的项目级别SKU。完整PLU的一个例子是:

'CuMaBfWh'  

其中' CuMa'是物品等级SKU和' Bf'和' Wh'分别是选择级别的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包含在&#39; GROUP BY&#39;条款,但我无法找到另一种方法。

有什么想法?所有建设性意见/批评都表示赞赏!

谢谢, 大卫

1 个答案:

答案 0 :(得分: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