SQL 子查询搞乱了分组依据

TSQL Sub Queries Are Messing Up Group By

提前感谢您提供的任何帮助。到目前为止,我在这里或其他地方的搜索中都找不到类似的东西,但我敢打赌更多,因为我不知道描述 issue/question.

的标准方法

我正在根据驻留在两个不同 table 中的数据构建查找代码。我们有可以与一个或多个选项相关联的菜单项。在这种情况下,我们正在处理咖喱(项目),它与一种肉(选择)和一种米饭(在同一选择 table 中找到的另一种选择)一起食用。完整的 PLU 是项目级别 SKU 与 2 个选择类别中每个类别的选择级别 SKU 串联而成。完整 PLU 的示例是:

'CuMaBfWh'  

其中 'CuMa' 是商品级别的 SKU,'Bf' 和 'Wh' 分别是选择级别的 SKU。我能够在外部查询中使用子查询(不喜欢它)来构建 PLU。问题是这种方法不允许我正确地分组数据。示例 tables、查询、有问题的输出和正确的输出如下。

给定这些 table 中的示例数据:

门票

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'

选择项

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'

正确的输出如下所示:

日期 PLU 数量
---- --- --- ------
2015 年 2 月 8 日 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

产生以下有问题的输出:

日期 PLU 数量
---- --- --- ------
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

我认为这是需要在 'GROUP BY' 子句中包含 ti.i_ticket_item_id 的结果,但我想不出另一种方法来做到这一点。

有什么想法吗?感谢所有建设性的advice/criticism!

谢谢, 大卫

我不明白 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