WedX - журнал о программировании и компьютерных науках

SQL - вернуть первое значение, отличное от NULL, после RANK () или ROW_NUMBER ()

Вопрос по следующему:

У меня есть таблица (клиент), которая содержит несколько записей с одним и тем же именем пользователя (к сожалению, это ограничение внешнего интерфейса программного обеспечения). Когда я присоединяюсь к этой таблице по имени пользователя, она, очевидно, возвращает несколько строк. Обычно я использую ROW_NUMBER (), разделяю по имени пользователя и порядку в нужном мне поле, а затем присоединяюсь, чтобы ограничить набор результатов одним и вернуть желаемые столбцы, и в прошлом это хорошо работало. Однако я пытаюсь использовать это так, как раньше ... Я разделяю по имени пользователя и упорядочиваю по дате последнего обновления записи, чтобы вернуть третье поле, в данном случае адрес . Обратите внимание на результаты следующей таблицы:

Username|UpdatedDate|Address
JSmith  |10-10-14   |NULL
JSmith  |05-24-14   |1 Main Street

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

Это возможно?

РЕДАКТИРОВАТЬ :

@Gordon ... возможно, я что-то не понимаю, но при первом подходе дата последнего обновления не учитывается при заказе. Итак, если таблица выглядит так:

JSmith|10-10-14|1 Main
JSmith|04-20-14|1 Main 
JSmith|01-10-13|5 Main

Он вернет 1 для всех строк. Конечная цель состоит в том, чтобы захватить только одну запись. Если имеется несколько записей, чтобы получить самую свежую запись, но затем, если адрес равен NULL, захватите следующую самую последнюю запись с адресом.


  • Просто используйте Where Address Is Not Null. Если самая последняя запись - NULL, она перейдет к первой заполненной записи. Если это не NULL, это не имеет значения / 16.07.2015
  • Но если есть только одна запись и использовать WHERE ADDRESS IS NOT NULL, она не вернет единственную запись, нет? 16.07.2015
  • @Пустой набор . . . Ваше редактирование не имеет смысла. Согласно вашим правилам, первая строка - это правильная строка, которую нужно вернуть. 22.07.2015
  • @GordonLinoff ... вы правы, мне нужна первая строка, но код вернет все три строки, поскольку все они будут иметь 1 для их ROW_NUMBER. Это был мой опыт, когда я изначально писал это. 27.07.2015

Ответы:


1

Просто используйте правильную row_number() логику:

select c.*
from (select c.*,
             row_number() over (partition by username
                                order by (case when address is not null then 1 else 2 end), UpdatedDate desc
                               ) as seqnum
      from clients c
     ) c
where seqnum = 1;

Конечно, если вы не против отфильтровать username, у которых нет адреса, вы можете использовать:

select c.*
from (select c.*,
             row_number() over (partition by username
                                order by UpdatedDate desc
                               ) as seqnum
      from clients c
      where address is not null
     ) c
where seqnum = 1;

Но вы можете потерять некоторые рекорды.

16.07.2015
  • Ваш второй подход - это то, с чего я начал, но вы правы, я теряю записи, где у нас есть только одна запись, но для этой записи нет адреса. Мне все еще нужно вернуть это. 16.07.2015
  • @Пустой набор . . . Отсюда первый подход. 17.07.2015
  • Я обновил свой исходный пост, чтобы, надеюсь, лучше объяснить, что я имел в виду. 21.07.2015

  • 2

    Используйте оператор apply, чтобы найти самый последний адрес в дополнение к row_number (), чтобы вы получили полную строку самых последних данных плюс самый последний адрес, даже если он окажется пустым в самой последней строке.

    SELECT
        c.*
    FROM (
        SELECT
            c.*
          , ROW_NUMBER() OVER (PARTITION BY username
                               ORDER BY UpdatedDate DESC) AS seqnum
          , COALESCE(c.address, oa.lastaddress) AS lastaddress
        FROM clients c
        OUTER APPLY (
            SELECT TOP (1)
                address AS lastaddress
            FROM clients c2
            WHERE c.username = c2.username
            AND c2.adress IS NOT NULL
            ORDER BY
                UpdatedDate DESC
        ) oa
    ) c
    WHERE seqnum = 1;
    
    10.10.2018
    Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]