2015-02-10 100 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