SQL запрос с отчетливым и групповым по снежинке - PullRequest
1 голос
/ 28 апреля 2020

То, что я пытаюсь выполнить sh, - это получить все записи для данного MPN, однако я хочу только самую последнюю DeliveryDate из shpm, но учитывая тот факт, что функция MAX должна быть в группе по предложению, он не получает последнюю запись, он получает все записи из-за отличного DeliveryDate, он получает две записи вместо одной, как я могу достичь этого? Это в снежинке.

Это мой SQL код

SELECT
    MD.MPN,
    MD.LOTCODE,
    MD.DATECODE,
    SHIP.ITEMCODE AS SYSTEMPARTNUMBER, 
    SHIP.SERIALNUMBER AS SYSTEMSERIALNUMBER, 
    SHIP.CUSTOMERNAME, 
    SHIP.SHIPTOADDRESS AS ADDRESS,
    SUM(IFNULL(SHIP.QUANTITY,0)) AS QUANTITY,
    SHIP.DELIVERYDATE
FROM cunits UNITS
   JOIN unc UC ON UC.CHILDUNITID = UNITS.ID
   JOIN shpm SHIP ON SHIP.SERIALNUMBER = UC.SYSSN
   JOIN tsern SN ON SN.UNITID = UNITS.ID
   JOIN machined MD ON MD.SERIALNUMBER = SN.SERIALNUMBER     
WHERE --SYSTEMSERIALNUMBER = '001801055469' and 
MPN = 'XC0402A105KP5CNN-S'
GROUP BY MD.MPN,MD.LOTCODE,MD.DATECODE,SHIP.ITEMCODE,SHIP.SERIALNUMBER,SHIP.CUSTOMERNAME,SHIP.SHIPTOADDRESS

Ответы [ 2 ]

2 голосов
/ 28 апреля 2020

Таким образом, угадывание некоторых данных для соответствия SQL

WITH cunits AS (
    SELECT * from values (1) v(id)
), unc AS (
    SELECT * FROM VALUES (1,'123') v(CHILDUNITID,SYSSN)
), shpm AS (
    SELECT * FROM VALUES ('a', '123', 10, '2020-02-01'),
       ('a', '123', 20, '2020-01-01') 
   v(ITEMCODE, SERIALNUMBER, QUANTITY, DELIVERYDATE)
), tsern AS (
    SELECT * FROM VALUES (1,'zxc') v(UNITID,SERIALNUMBER)
), machined as (
    SELECT * FROM VALUES ('zxc', 'XC0402A105KP5CNN-S') v(SERIALNUMBER, MPN)
)

и отбрасывание некоторых столбцов, которые не имеют значения из примера

SELECT
    MD.MPN,
    SHIP.ITEMCODE AS SYSTEMPARTNUMBER, 
    SHIP.SERIALNUMBER AS SYSTEMSERIALNUMBER, 
    SUM(IFNULL(SHIP.QUANTITY,0)) AS QUANTITY,
    SHIP.DELIVERYDATE
FROM cunits UNITS
   JOIN unc UC ON UC.CHILDUNITID = UNITS.ID
   JOIN shpm SHIP ON SHIP.SERIALNUMBER = UC.SYSSN
   JOIN tsern SN ON SN.UNITID = UNITS.ID
   JOIN machined MD ON MD.SERIALNUMBER = SN.SERIALNUMBER     
WHERE 
MPN = 'XC0402A105KP5CNN-S'
GROUP BY MD.MPN,SHIP.ITEMCODE,SHIP.SERIALNUMBER;

сейчас SHIP.DELIVERYDATE должно быть добавлен к предложению group by, иначе этот код никогда не запустится, даже если вы игнорируете ваше желание не видеть данные 2020-01-01

, как только вы добавите, что получите две строки, которые вам не нужны.

MPN SYSTEMPARTNUMBER    SYSTEMSERIALNUMBER  QUANTITY    DELIVERYDATE
XC0402A105KP5CNN-S  a   123 10  2020-02-01
XC0402A105KP5CNN-S  a   123 20  2020-01-01

Решение Гордона, чтобы добавить QUALIFY

QUALIFY ROW_NUMBER() OVER (PARTITION BY MD.MPN, SHIP.SERIALNUMBER ORDER BY SHIP.DELIVERYDATE DESC) = 1;

правильно дает ответ, но вычисляет все результаты и отбрасывает те, которые не нужны последним ... где в зависимости от размера вашего набора данных и как в вашей таблице shpm находится много строк, CTE для предварительной фильтрации может работать лучше ..

WITH cunits AS (
    SELECT * from values (1) v(id)
), unc AS (
    SELECT * FROM VALUES (1,'123') v(CHILDUNITID,SYSSN)
), shpm AS (
    SELECT * FROM VALUES ('a', '123', 10, '2020-02-01'),
       ('a', '123', 20, '2020-01-01') 
   v(ITEMCODE, SERIALNUMBER, QUANTITY, DELIVERYDATE)
), tsern AS (
    SELECT * FROM VALUES (1,'zxc') v(UNITID,SERIALNUMBER)
), machined as (
    SELECT * FROM VALUES ('zxc', 'XC0402A105KP5CNN-S') v(SERIALNUMBER, MPN)
), pre_filtered_shpm AS (
    select * from shpm
    QUALIFY ROW_NUMBER() OVER (PARTITION BY SERIALNUMBER ORDER BY DELIVERYDATE DESC) = 1
)
SELECT
    MD.MPN,
    SHIP.ITEMCODE AS SYSTEMPARTNUMBER, 
    SHIP.SERIALNUMBER AS SYSTEMSERIALNUMBER, 
    SUM(IFNULL(SHIP.QUANTITY,0)) AS QUANTITY,
    SHIP.DELIVERYDATE
FROM cunits UNITS
   JOIN unc UC ON UC.CHILDUNITID = UNITS.ID
   JOIN pre_filtered_shpm SHIP ON SHIP.SERIALNUMBER = UC.SYSSN
   JOIN tsern SN ON SN.UNITID = UNITS.ID
   JOIN machined MD ON MD.SERIALNUMBER = SN.SERIALNUMBER     
WHERE 
MPN = 'XC0402A105KP5CNN-S'
GROUP BY MD.MPN,SHIP.ITEMCODE,SHIP.SERIALNUMBER,SHIP.DELIVERYDATE;
2 голосов
/ 28 апреля 2020

Используйте ROW_NUMBER() и QUALIFY:

SELECT MD.MPN, MD.LOTCODE, MD.DATECODE,
       SHIP.ITEMCODE AS SYSTEMPARTNUMBER, SHIP.SERIALNUMBER AS SYSTEMSERIALNUMBER, 
       SHIP.CUSTOMERNAME, SHIP.SHIPTOADDRESS AS ADDRESS,
       SUM(COALESCE(SHIP.QUANTITY, 0)) AS QUANTITY,
       SHIP.DELIVERYDATE
FROM cunits UNITS JOIN
     unc UC
     ON UC.CHILDUNITID = UNITS.ID JOIN
     shpm SHIP
     ON SHIP.SERIALNUMBER = UC.SYSSN JOIN
     tsern SN
     ON SN.UNITID = UNITS.ID JOIN
     machined MD
     ON MD.SERIALNUMBER = SN.SERIALNUMBER     
WHERE '001801055469' and MPN = 'XC0402A105KP5CNN-S'
GROUP BY MD.MPN, MD.LOTCODE, MD.DATECODE, SHIP.ITEMCODE, SHIP.SERIALNUMBER, SHIP.CUSTOMERNAME, SHIP.SHIPTOADDRESS
QUALIFY ROW_NUMBER() OVER (PARTITION BY MD.MPN, SHIP.SERIALNUMBER ORDER BY SHIP.SHIPDATE DESC) = 1;

Это возвращает в строке на MPN, как я понимаю ваш вопрос. Возможно, вам понадобятся и другие столбцы в PARTITION BY.

...