SQL-преобразовать широкую таблицу в длинную с помощью 3 специальных правил

У меня есть следующая таблица:

Individual   Organisation   Time1        Time2        T_diff   Time1_original
111          2              01-04-2020   01-05-2020   1        01-04-2020
111          2              01-05-2020   01-04-2021   11       01-04-2020
122          2              01-04-2020   01-01-2021   9        01-04-2020
122          3              01-01-2021                         01-01-2021

Я хотел бы преобразовать его в следующий:

Individual      Organisation      Times      
111             2                 01-04-2020 (Time1-line1)
111             2                 01-04-2021 (Time2-line2)
122             2                 01-04-2020 (Time1)
122             2                 01-01-2021 (Time2)
122             3                 01-01-2021 (Time1)

3 условия:

Для каждого Individual-Organisation,

Если (T_diff <= 3 ИЛИ T_diff IS NULL) И Time1 EQUAL TO Time1_original принести Time1

Если T_diff > 3 и Time1 NOT EQUAL TO Time1_original принести Time2

Если T_diff > 3 и Time1 EQUAL TO Time1_original принести Time1 и Time2

Как я могу сделать это в SQL?

Вам нужно пометить свою РСУБД TAG

Stu 10.04.2022 19:15

Я включил это сейчас, спасибо @Stu

Daniela Rodrigues 10.04.2022 19:20
Получение данных из формы с помощью JavaScript - краткое руководство
Получение данных из формы с помощью JavaScript - краткое руководство
Получить данные из формы с помощью JS очень просто: вы запрашиваете элемент формы, передаете его конструктору new FormData() и, наконец, получаете...
Пользовательские правила валидации в Laravel
Пользовательские правила валидации в Laravel
Если вы хотите создать свое собственное правило валидации, Laravel предоставляет возможность сделать это. Создайте правило с помощью следующей...
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
1
2
25
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ваши требования включают несколько поворотный столбцов в строки.

Ваши имена столбцов немного вводят в заблуждение, имея даты, а не раз; В идеале вы должны указать даты в формате ГГГГММДД, похоже, вы используете ДД-ММ-ГГГГ.

боковое соединение упрощает эту задачу, в SQL Server это делается с помощью применять().

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

with timeywimey as (
    select * 
    from t
    cross apply(values
      (case 
        when (t_diff <= 3 or t_diff is null) and time1 = time1_original then time1 
        else 
          case when t_diff > 3 then
            iif(time1 = time1_original, time1, time2)
          end 
        end
        ),
        (case when t_diff > 3 and time1 = time1_original then time2 end)
    )v(Times)
)
select individual, organisation, times 
from timeywimey 
where Times is not null;

См. Демонстрационная БД<>Скрипка

Большое спасибо @Stu, в строке 16 должно быть написано «Times» вместо «times», верно? Также «если», а не «iif», строка 9, верно? Я знаю, что сказал, что использую SQL Server, потому что я обычно следую этому формату и работаю. Но на этот раз у меня не работает. Я использую HiveQL, извините за путаницу, обычно работает, но на этот раз не работает. Это может быть перекрестное применение.

Daniela Rodrigues 10.04.2022 20:03

Извините за редактирование моих данных, я думал, что этих примеров будет достаточно, поэтому я изменил их. Мое время действительно является датой, и я использую ГГГГММДД. Я обновлю свой вопрос.

Daniela Rodrigues 10.04.2022 20:06

@DanielaRodrigues Решение предназначено для SQL Server, указанной вами СУБД. Я ничего не знаю о HiveQL — iif является «встроенным if» — в некоторых продуктах, например MySql, это является просто if, так что попробуйте это; это просто более компактная версия кейс, поэтому, если она не работает, вы можете заменить ее выражением case; как вы можете видеть из демонстрационного Fiddle, он работает — в SQL Server! Это не имеет значения times vs Times - SQL нечувствителен к регистру.

Stu 10.04.2022 20:06

Да, ваше решение работает в SQL Server, спасибо за помощь @Stu. Я избегал упоминать HiveQL только потому, что, кажется, никто не знает об этом языке, поэтому я думал, что никогда не получу никаких ответов. К сожалению, это решение не переводится на HiveQL.

Daniela Rodrigues 10.04.2022 20:24

так что, если честно, это не неожиданно, у каждой СУБД есть свой диалект для некоторых функций - вам, должно быть, повезло, что другие ответы для SQL Server сработали. Вы, вероятно, можете взять этот принцип и достаточно легко перевести его, например, когда я Google, я вижу, что существует множество вопросов об использовании SQL Server Apply в HiveQL.

Stu 10.04.2022 20:26

Если окажется, что он не переносим, ​​вы можете сделать то же самое, разделив cross apply() на два запроса объединенный.

Stu 10.04.2022 20:31

Я так не думаю, к сожалению. Как бы вы это сделали, два объединенных запроса вместо перекрестного применения? Я попытался создать дополнительную переменную, используя логику регистра, но это не сработало, потому что мне также нужно сделать какое-то широкое или длинное изменение формы для создания новых строк.

Daniela Rodrigues 10.04.2022 20:38

@DanielaRodrigues Я преобразовал запрос в объединение, см. другой ответ.

Stu 10.04.2022 20:55

Добавление еще одного ответа, так как мой другой ответ легко преобразовать в версию, более совместимую с ANSI, с помощью союз. Я думаю, что это с большей вероятностью будет работать в HiveQL.

with timey as (
  select *, 
    case 
      when (T_diff <= 3 or T_diff is null) and Time1 = Time1_original then Time1 
      else 
        case when T_diff > 3 then
          case when Time1 = Time1_original then Time1 else Time2 end
        end 
      end as Times
    from t
  union all
  select *, 
    case when T_diff > 3 and Time1 = Time1_original then Time2 end as Times
  from t
)
select Individual, Organisation, Times
from timey
where Times is not null
order by Individual, Times;

БД СКРИПКА

Это решение отлично работает в HiveQL. Не могу отблагодарить тебя @Stu

Daniela Rodrigues 10.04.2022 21:09

Круто, тогда это победа.

Stu 10.04.2022 21:10

Другие вопросы по теме