SQL | Как разделить один столбец дат на два столбца в таблице SQL - PullRequest
0 голосов
/ 09 июня 2018

Спасибо за просмотр моего запроса, мне нужны следующие предложения:

  • Как разбить столбец с одной датой на два столбца в TSQL
  • У меня есть таблица SQL, которая представляет собойhotel CheckInDate Проблема, в которую входят эти записи, включает CheckOutDate, которая записана в том же столбце, но с идентификатором записи, поэтому каждый идентификатор будет иметь две строки записей в одном столбце.
  • Я хочу разделить эту дату на основе двух столбцов(CheckInDate и CheckOutDate), CheckOutDate будет вторым столбцом, будет псевдоним.
  • Я хотел бы видеть все записи на основе их идентификатора.

Любое предложение будет оценено.

Исходная таблица

Это результаты, которые я хотел бы видеть, последний столбец - это разность дат, DATEDIFF (d, [Date], [Date]) AS DaysBooked

Исходные поля таблицы

SELECT  
    [ID]
    ,([Date])  AS CheckInDate
  FROM [DateOneRow]

Я пробовал нижеприведенный код, но не работал

SELECT  
--I would like to have below to columns
    ([ID])
     ,MIN([Date])     AS CheckInDate
     ,MAX([DATE])     AS CheckOutDate
     ,DATEDIFF(d,[Date],[Date]) AS DaysBooked
  FROM [DateOneRow]
  GROUP BY      [ID],  ([Date])

[Исходная таблица] [введите описание изображения здесь] 1

DDL добавлено @shawnt00

create table DateOneRow (Id int not null, "Date" date not null);
insert into DateOneRow ("Date", Id) values
    ('20181201', 1), ('20181204', 1),
    ('20180201', 2), ('20180301', 2),
    ('20180301', 1), ('20180303', 1),
    ('20180402', 2), ('20180503', 2),
    ('20180120', 2), ('20180202', 2);

Ответы [ 3 ]

0 голосов
/ 09 июня 2018

Если бы у нас был только идентификатор бронирования, это было бы довольно просто.Но мы можем получить номер бронирования для [Id] (я полагаю, это клиент, который забронировал?) С помощью

ceiling(row_number() OVER (PARTITION BY [DateOneRow].[Id] ORDER BY [DateOneRow].[CheckInDate]) / convert(decimal, 2))

row_number() OVER (PARTITION BY [DateOneRow].[Id] ORDER BY [DateOneRow].[CheckInDate]) будет нумеровать строки для [Id], заказанного [CheckInDate].Каждые две строки (в порядке, определенном [CheckInDate]) принадлежат одному бронированию.Таким образом, мы можем разделить число на 2 и ceiling(), чтобы получить номер бронирования, к которому относится строка.

Таким образом, мы можем легко GROUP BY [Id] и номер бронирования, взяв минимальную дату в качестве времени регистрациии максимум как время оформления заказа.Примените datediff() к этому, и все готово.

SELECT [X].[Id],
       min([X].[CheckInDate]) [CheckInDate],
       max([X].[CheckInDate]) [CheckOutDate],
       datediff(d, min([X].[CheckInDate]), max([X].[CheckInDate])) [DaysBooked]
       FROM (SELECT [DateOneRow].[Id],
                    [DateOneRow].[CheckInDate],
                    ceiling(row_number() OVER (PARTITION BY [DateOneRow].[Id]
                                               ORDER BY [DateOneRow].[CheckInDate]) / convert(decimal, 2)) [Booking#]
                    FROM [DateOneRow]) [X]
       GROUP BY [X].[Id],
                [X].[Booking#];

(Вы можете рассмотреть возможность использования datediff(d, min([X].[CheckInDate]), max([X].[CheckInDate])) + 1 [DaysBooked] (обратите внимание на + 1), если даты включительно.)

db <> fiddle

Но я настоятельно рекомендую пересмотреть этот ужасный дизайн!


Редактировать:

Если [Id] на самом делеидентификатор бронирования и тот же только для двух строк, принадлежащих одному бронированию, это будет просто GROUP BY с использованием min() и max().

SELECT [DateOneRow].[Id],
       min([DateOneRow].[CheckInDate]) [CheckInDate],
       max([DateOneRow].[CheckInDate]) [CheckOutDate],
       datediff(d, min([DateOneRow].[CheckInDate]), max([DateOneRow].[CheckInDate])) [DaysBooked]
       FROM [DateOneRow]
       GROUP BY [DateOneRow].[Id];
0 голосов
/ 09 июня 2018

Если ваши проверки всегда корректно сопряжены с проверкой, то что-то вроде этого должно работать:

-- option 1
with data as (
    select *, row_number() over (partition by Id order by "Date") - 1 as rn
    from DateOneRow
)
select
    d1."Date" as CheckInDate, d2."Date" as CheckOutDate,
    datediff(day, d1."Date", d2."Date") as DaysBooked
from data d1 inner join data d2 on d2.Id = d1.Id and d2.rn = d1.rn + 1
where d1.rn % 2 = 0;


-- option 2
with data as (
    select *, row_number() over (partition by Id order by "Date") - 1 as rn
    from DateOneRow
)
select
    d1."Date" as CheckInDate, d2."Date" as CheckOutDate,
    datediff(day, d1."Date", d2."Date") as DaysBooked
from data d1 cross apply
    (
    select min("Date") as "Date" from data
    where Id = d1.Id and "Date" > d1."Date"
    ) d2
where d1.rn % 2 = 0;

Я даю вам второй вариант, если это быстрее.

http://rextester.com/LHSZ1605

0 голосов
/ 09 июня 2018

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

Для SQL Server:

create table [DateOneRow] (
  [Id] int,
  [Date] date
);

insert into [DateOneRow] ([Id], [Date]) values (1, '2018-01-01');
insert into [DateOneRow] ([Id], [Date]) values (1, '2018-01-03');
insert into [DateOneRow] ([Id], [Date]) values (2, '2018-02-15');
insert into [DateOneRow] ([Id], [Date]) values (2, '2018-02-16');
insert into [DateOneRow] ([Id], [Date]) values (3, '2018-03-20');
insert into [DateOneRow] ([Id], [Date]) values (4, '2018-04-25');

select
    ci.id,
    check_in,
    check_out,
    datediff(day, check_in, check_out) as days_booked
  from (
    select id, min(date) as check_in from dateonerow group by id
  ) ci
  full join (
    select id, max(date) as check_out from dateonerow group by id
  ) co on ci.id = co.id

Результат:

id  check_in    check_out   days_booked
--  ----------  ----------  -----------
1   2018-01-01  2018-01-03  2
2   2018-02-15  2018-02-16  1
3   2018-03-20  2018-03-20  0
4   2018-04-25  2018-04-25  0

Для MySQL:

create table DateOneRow (
  Id int,
  Date date
);

insert into DateOneRow (Id, Date) values (1, '2018-01-01');
insert into DateOneRow (Id, Date) values (1, '2018-01-03');
insert into DateOneRow (Id, Date) values (2, '2018-02-15');
insert into DateOneRow (Id, Date) values (2, '2018-02-16');
insert into DateOneRow (Id, Date) values (3, '2018-03-20');
insert into DateOneRow (Id, Date) values (4, '2018-04-25');

select 
    ci.id, 
    ci.check_in, 
    co.check_out, 
    datediff(check_out, check_in) as days_booked
  from (
    select id, min(date) as check_in from DateOneRow group by id
  ) ci
  join (
    select id, max(date) as check_out from DateOneRow group by id
  ) co on ci.id = co.id;

Результат:

id  check_in    check_out   days_booked
--  ----------  ----------  -----------
1   2018-01-01  2018-01-03  2
2   2018-02-15  2018-02-16  1
3   2018-03-20  2018-03-20  0
4   2018-04-25  2018-04-25  0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...