Ранжирование и разделение SQL ПО

#sql #sql-server

#sql #sql-сервер

Вопрос:

Мне всего два дня в SQL. Я пытаюсь обновить базу данных, в которой я хочу, чтобы в базе данных оставались только те строки для каждого уникального идентификатора, для которого серийный номер (Sl_No.) является наивысшим, а inspection_type содержит «PMCR».

Снимок данных:-

введите описание изображения здесь

Требуется вывод:-

введите описание изображения здесь

Ниже приведен код, который я мог бы написать до сих пор.

 select * from (
            Select Identifier, 
                   Sl_No, 
                   Inspection_Type, 
                   RANK() Over (Partition by Identifier Order By SI_No Desc) AS Rnk
            from copy_of_inspection_response
            where (Inspection_Type like '%PMCR%')
            )
 

Ошибка, которую я получаю, это :-

введите описание изображения здесь

Я перепробовал все, но не могу найти какое-либо решение и не уверен, почему оно показывает синтаксическую ошибку,

Любая помощь будет высоко оценена!!

Спасибо!!

Комментарии:

1. Нет необходимости в подзапросе, просто сделайте Select Identifier, ... from copy_of_inspection_response where Inspection_Type like '%PMCR%' .

Ответ №1:

просто добавьте псевдоним в конце вложенного запроса.

 select * from (
            Select Identifier, 
                   Sl_No, 
                   Inspection_Type, 
                   RANK() Over (Partition by Identifier Order By SI_No Desc) AS Rnk
            from copy_of_inspection_response
            where (Inspection_Type like '%PMCR%')
            ) u
 

Ответ №2:

Использование псевдонима после вашего последнего «)» исправит ошибку, но не даст ожидаемого результата. Вам нужно выбрать одну строку с наибольшим si_no для каждого идентификатора.

Пожалуйста, используйте следующий запрос

 with cte as (
            Select Identifier, 
                   Sl_No, 
                   Inspection_Type, 
                   Rank() Over (Partition by Identifier Order By SI_No Desc) AS Rnk
            from copy_of_inspection_response
            where (Inspection_Type like '%PMCR%')
            )
select * from cte where Rnk=1
 

Чтобы удалить все остальные строки, используйте запрос ниже:

 with cte as (
                Select Identifier, 
                       Sl_No, 
                       Inspection_Type, 
                       Rank() Over (Partition by Identifier Order By SI_No Desc) AS Rnk
                from copy_of_inspection_response
                where (Inspection_Type like '%PMCR%')
                ) delete cte where Rnk>1
 

Комментарии:

1. Это работает, но не удаляет необязательные строки, не могли бы вы помочь мне, как это сделать в рамках одного запроса

2. Добавлен запрос для удаления нужных строк.

3. @ss_0708 Пожалуйста, дайте мне знать ваши отзывы.

4. Да, это помогло, большое спасибо

Ответ №3:

Используйте not exists следующим образом:

 select * from copy_of_inspection_response t
 where t.Inspection_Type like '%PMCR%'
   and not exists 
       (select 1 from copy_of_inspection_response tt
         where tt.Identifier  = t.Identifier 
           and tt.Inspection_Type like '%PMCR%'  
           and tt.SI_No > t.SI_No )
 

Если вы хотите delete из таблицы, используйте exists следующее:

 delete from t
from copy_of_inspection_response  t
where t.Inspection_Type like '%PMCR%'
   and exists 
       (select 1 from copy_of_inspection_response tt
         where tt.Identifier  = t.Identifier 
           and tt.Inspection_Type like '%PMCR%'  
           and tt.SI_No > t.SI_No )
 

Комментарии:

1. Да ладно, у нас это было как агрегат окна, а вы переписали как самостоятельное объединение? Для чего? Все, что требовалось для операции, — это псевдоним

2. Я давал другой способ сделать то же самое. Что не так, если OP знает, как он может достичь одного и того же двумя разными способами.

3. Я знаю, но на самом деле вам также следует объяснить недостатки этого ответа (дополнительные запросы и т. Д.) @ ss_0708 Исправил это для вас

4. @Charlieface _ Большое вам спасибо, это сработало для меня,