Предложение WITH: Включает только определенные значения из каждой таблицы - PullRequest
0 голосов
/ 15 января 2019

Я пытаюсь написать запрос, который получит количество мест для определенного SKU в каждой «зоне расположения», а затем общее количество всех мест для целей консолидации.

Это код, который я использую для попытки:

WITH 
    C0R_Count AS (
        SELECT sku_id, count(location_id) as Bulk_Count
        FROM Inventory
        where location_id like 'C0R%'
        group by sku_id),
    C0S_Count AS (
        SELECT sku_id, count(location_id) as Bin_Count
        FROM Inventory
        where location_id like 'C0S%'
        group by sku_id)
SELECT RANK() OVER (ORDER BY Bin_Count+Bulk_Count DESC)as Count_Rank,
        Inventory.sku_id, Bin_Count, Bulk_Count, 
        (Bin_Count+Bulk_Count) as Total_Count
FROM Inventory, C0R_Count, C0S_Count
WHERE client_id = 'SDRY-US' 
   and site_id = 'USCOL1' 
   and Inventory.Sku_id = C0R_Count.Sku_id 
   and Inventory.Sku_id = C0S_Count.Sku_id 
   and (Bin_Count+Bulk_Count) > 9
GROUP BY Inventory.sku_id, Bin_Count, Bulk_Count
;

То, что происходит, - это результат, включающий только SKU, которые имеют хотя бы одно местоположение для Bulk_Count и Bin_Count .

Например, есть конкретный SKU, который отображается в 223 (Bin Count) местоположениях, но не отображается в местоположениях Bulk_Count. Это лучшие результаты, показанные с использованием текущего запроса, но SKU с общим счетом 223 будет иметь ранг 1, но его исключение, так как Bulk Count будет 0

COUNT_RANK  SKU_ID            BIN_COUNT  BULK_COUNT   TOTAL_COUNT
1           M10003NS-02A-.M    71        2                73
2           M10003NS-02A-.S    68        2                70
3           M10003NS-02A-.L    60        4                64
4           M10003NS-02A-.XL   61        2                63

Добавил следующее с использованием явной записи соединения и получил те же результаты.


WITH 
    C0R_Count AS (
        SELECT /*+ materialize */ 
        sku_id, count(location_id) as Bulk_Count
        FROM Inventory
        where location_id like 'C0R%'
        group by sku_id),
    C0S_Count AS (
        SELECT /*+ materialize */ 
        sku_id, count(location_id) as Bin_Count
        FROM Inventory
        where location_id like 'C0S%'
        group by sku_id)
SELECT RANK() OVER (ORDER BY Bin_Count+Bulk_Count DESC)as Count_Rank,
       Inventory.sku_id, Bin_Count, Bulk_Count, 
       (Bin_Count+Bulk_Count) as Total_Count
FROM Inventory
Left Join C0R_Count
   on Inventory.Sku_id = C0R_Count.Sku_id
Left Join C0S_Count
   on Inventory.Sku_id = C0S_Count.Sku_id
WHERE 
   client_id = 'SDRY-US' 
   and site_id = 'USCOL1' 
   and (Bin_Count+Bulk_Count) > 9
GROUP BY Inventory.sku_id, Bin_Count, Bulk_Count
;

Ответы [ 3 ]

0 голосов
/ 16 января 2019

Ваш запрос выглядит намного сложнее, чем нужно. Вы можете сделать все это с помощью условного агрегирования и без подзапросов или CTE:

select rank() over (order by sum(case when location_id like 'C0R%' or location_id like 'C0s%' then 1 else 0 end) desc) as count_rank,
       sku_id,
       sum(case when location_id like 'C0R%' then 1 else 0 end) as Bulk_Count
       sum(case when location_id like 'C0S%' then 1 else 0 end) as Bin_Count
from Inventory i
where client_id = 'SDRY-US' and site_id = 'USCOL1' 
group by sku_id
having sum(case when location_id like 'C0R%' or location_id like 'C0s%' then 1 else 0 end) > 9;

Вы можете ввести подзапрос только для упрощения псевдонимов столбцов:

select rank() over (order by Bulk_Count + Bin_Count desc) as count_rank,
       i.*
from (select sku_id,
             sum(case when location_id like 'C0R%' then 1 else 0 end) as Bulk_Count
             sum(case when location_id like 'C0S%' then 1 else 0 end) as Bin_Count
      from Inventory i
      where client_id = 'SDRY-US' and site_id = 'USCOL1' 
      group by sku_id
     ) i
where Bulk_Count + Bin_Count > 9
0 голосов
/ 16 января 2019

Вы можете попробовать это:

WITH 
    C0R_Count AS (
        SELECT /*+ materialize */ 
        sku_id, count(location_id) as Bulk_Count
        FROM Inventory
        where location_id like 'C0R%'
        group by sku_id),
    C0S_Count AS (
        SELECT /*+ materialize */ 
        sku_id, count(location_id) as Bin_Count
        FROM Inventory
        where location_id like 'C0S%'
        group by sku_id)
SELECT RANK() OVER (ORDER BY nvl(Bin_Count,0)+nvl(Bulk_Count,0) DESC)as Count_Rank,
       Inventory.sku_id, Bin_Count, Bulk_Count, 
       (nvl(Bin_Count,0)+nvl(Bulk_Count,0)) as Total_Count
FROM Inventory
Left Join C0R_Count
   on Inventory.Sku_id = C0R_Count.Sku_id
Left Join C0S_Count
   on Inventory.Sku_id = C0S_Count.Sku_id
WHERE 
   client_id = 'SDRY-US' 
   and site_id = 'USCOL1' 
   and (nvl(Bin_Count,0)+nvl(Bulk_Count,0)) > 9
GROUP BY Inventory.sku_id, Bin_Count, Bulk_Count
;

При вычислении нулевых значений они становятся нулевыми.

0 голосов
/ 15 января 2019

Я опубликую это как ответ - вам нужно , чтобы использовать синтаксис LEFT/RIGHT JOIN здесь. СУБД будет логически интерпретировать ваш существующий SQL, чтобы неявно означать INNER объединения.

Кроме того, вам может понадобиться пересмотреть ваши GROUP BY предложения.

Возможно, вам потребуется использовать подзапросов - сначала выберите интересующие строки, а затем суммируйте их.

...