Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как организовать "срез последних/последних"?
Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7 > Программисту > Базы данных
Vofka
Привет!

Интересует вопрос, как организовать срез последних?

Т.е. есть таблица: id | id_chel (ид человека) | mesto_raboty (место работы) | data (дата). В таблице хранятся люди, место работы и дата. Меняя место работы - мы просто добавляем новую запись, например

1 | Петров | ЧП "У Васи" | 1.10.2010
2 | Иванов | ЧП "У Пети" | 1.10.2010
3 | Петров | ЧП "У Коли" | 5.10.2010
...

Это не связано с 1С. Это просто таблица в какой-нибудь СУБД (MSSQL, MySQL...). Интересует как из такой таблицы получить то, что в 1С называется срезом первых/последних. Интересна сама логика, т.е. указать какое-то условие в запросе или использовать какую-то специальную функцию.
Log1c
Цитата(Vofka @ 11.10.10, 9:25) необходимо зарегистрироваться для просмотра ссылки
Привет!

Интересует вопрос, как организовать срез последних?

Т.е. есть таблица: id | id_chel (ид человека) | mesto_raboty (место работы) | data (дата). В таблице хранятся люди, место работы и дата. Меняя место работы - мы просто добавляем новую запись, например

1 | Петров | ЧП "У Васи" | 1.10.2010
2 | Иванов | ЧП "У Пети" | 1.10.2010
3 | Петров | ЧП "У Коли" | 5.10.2010
...

Это не связано с 1С. Это просто таблица в какой-нибудь СУБД (MSSQL, MySQL...). Интересует как из такой таблицы получить то, что в 1С называется срезом первых/последних. Интересна сама логика, т.е. указать какое-то условие в запросе или использовать какую-то специальную функцию.


С понятием среза данных не знаком. Сформулируйте пожалуйста что нужно получить в результирующей выборке?
Flexy
SELECT Max(data), id, id_chel, mesto_raboty
from Ваша База
WHERE id='код'
group by id()
Vofka
Цитата
С понятием среза данных не знаком. Сформулируйте пожалуйста что нужно получить в результирующей выборке?

Нужно получить последние (по дате добавления) записи.

Цитата
SELECT Max(data), id, id_chel, mesto_raboty
from Ваша База
WHERE id='код'
group by id()

Допустим можно smile.gif . Ещё варианты есть? smile.gif
World1С
Select * 
from base as b1
where Date in (Select MAX(Date) from base as b2 where b1.id=b2.id)


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

Select Max(Date), id 
from base
group by id (ну и все остальные поля которые будут в селекте после id)
РомаZ
Примерно так:

// Входные параметры: 
//           @someDate: DATETIME

SELECT
    srcTable.id
    ,srcTable.Name
    ,srcTable.someOtherProperty
    ,srcTable.Date AS [Дата последнего изменения]
    ,@someDate AS [Дата среза]
    
FROM
    dbTable AS srcTable    // отсюда получаем информацию по id-ам из constraintaTable
    
    INNER JOIN
    (    // Получение последних идентификаторов на дату с дополнительными условиями
        SELECT
            dbTable.id,
            max(dbTable.data)
        FROM dbTable
        WHERE dbTable.data < @someDate
            AND дополнительные условия на отбор по данным таблицы
    ) AS constraintTable
    
    ON srcTable.id = constraintTable.id
    AND srcTable.data = constraintTable.data


Цитата(РомаZ @ 09.06.11, 13:24) необходимо зарегистрироваться для просмотра ссылки


забыл "Group By".

Вот код с исправлением:

// Входные параметры: 
//           @someDate: DATETIME

SELECT
    srcTable.id
    ,srcTable.Name
    ,srcTable.someOtherProperty
    ,srcTable.Date AS [Дата последнего изменения]
    ,@someDate AS [Дата среза]
    
FROM
    dbTable AS srcTable    // отсюда получаем информацию по id-ам из constraintaTable
    
    INNER JOIN
    (    // Получение последних идентификаторов на дату с дополнительными условиями
        SELECT
            dbTable.id,
            max(dbTable.data)
        FROM dbTable
        WHERE dbTable.data < @someDate
        //    AND дополнительные условия на отбор по данным таблицы
        
        [b]GROUP BY dbTable.id[/b]
        
    ) AS constraintTable
    
    ON srcTable.id = constraintTable.id
    AND srcTable.data = constraintTable.data
Pepe
Можно построить индекс и отбор по полю дата, можно без индекса найти последнюю запись и идти назад по условию. При работе с ДБФ легко в Visual Foxpro, да и в 1С реализуется, если я правильно понял задание.
szhukov
Цитата(РомаZ @ 09.06.11, 14:35) необходимо зарегистрироваться для просмотра ссылки
Примерно так:

// Входные параметры: 
//           @someDate: DATETIME

SELECT
    srcTable.id
    ,srcTable.Name
    ,srcTable.someOtherProperty
    ,srcTable.Date AS [Дата последнего изменения]
    ,@someDate AS [Дата среза]
    
FROM
    dbTable AS srcTable    // отсюда получаем информацию по id-ам из constraintaTable
    
    INNER JOIN
    (    // Получение последних идентификаторов на дату с дополнительными условиями
        SELECT
            dbTable.id,
            max(dbTable.data)
        FROM dbTable
        WHERE dbTable.data < @someDate
            AND дополнительные условия на отбор по данным таблицы
    ) AS constraintTable
    
    ON srcTable.id = constraintTable.id
    AND srcTable.data = constraintTable.data


забыл "Group By".

Вот код с исправлением:

// Входные параметры: 
//           @someDate: DATETIME

SELECT
    srcTable.id
    ,srcTable.Name
    ,srcTable.someOtherProperty
    ,srcTable.Date AS [Дата последнего изменения]
    ,@someDate AS [Дата среза]
    
FROM
    dbTable AS srcTable    // отсюда получаем информацию по id-ам из constraintaTable
    
    INNER JOIN
    (    // Получение последних идентификаторов на дату с дополнительными условиями
        SELECT
            dbTable.id,
            max(dbTable.data)
        FROM dbTable
        WHERE dbTable.data < @someDate
        //    AND дополнительные условия на отбор по данным таблицы
        
        [b]GROUP BY dbTable.id[/b]
        
    ) AS constraintTable
    
    ON srcTable.id = constraintTable.id
    AND srcTable.data = constraintTable.data


Не взлетит, потому что вложенный запрос:
        SELECT
            dbTable.id,
            max(dbTable.data)
        FROM dbTable
        WHERE dbTable.data < @someDate


вернет все записи smile.gif

Это делается не так
Vofka
Апну тему smile.gif

Цитата(Flexy @ 25.01.11, 17:12) необходимо зарегистрироваться для просмотра ссылки
SELECT Max(data), id, id_chel, mesto_raboty
from Ваша База
WHERE id='код'
group by id()

Так и что это получится? Запрос вообще по ходу не отработает, потому что нет группировок по остальным полям. А если добавить группировки, то по всем полям, то получится на выходе эта же таблица в исходном виде.

Цитата(World1С @ 26.01.11, 10:36) необходимо зарегистрироваться для просмотра ссылки
Select * from base as b1 where Date in (Select MAX(Date) from base as b2 where b1.id=b2.id)

По-моему так нельзя. Какие связи в условии IN ?

Цитата(World1С @ 26.01.11, 10:36) необходимо зарегистрироваться для просмотра ссылки
Select Max(Date), id from base group by id (ну и все остальные поля которые будут в селекте после id)

Тоже не то пальто, группировка по Id ничего не даст, вернутся все записи, потому что Id каждой записи разный.

Цитата(Pepe @ 09.06.11, 15:55) необходимо зарегистрироваться для просмотра ссылки
Можно построить индекс и отбор по полю дата, можно без индекса найти последнюю запись и идти назад по условию. При работе с ДБФ легко в Visual Foxpro, да и в 1С реализуется, если я правильно понял задание.

Речь идет про чистый SQL запрос.

Т.е. не один вариант в этой теме, по-моему, не правильный. Предложу свой:

SELECT
    id,
    id_chel,
    mesto_raboty,
    data
FROM
    table AS table
    INNER JOIN
        (
        SELECT
            Max(Data) AS data,
            id_chel
        FROM
            table AS table
        GROUP BY
            id_chel
        ) AS filter
    ON table.id_chel = filter.id_chel
        AND table.data = filter.data
Vola
Vofka @ 11.10.10, 8:25 необходимо зарегистрироваться для просмотра ссылки ,

А можно воспользоваться оконной аналитической функцией FIRST_VALUE

--Создание временной таблицы с начальными данными, предварительно проверив временную таблицу на существование
IF OBJECT_ID(N'tempdb..#InitialData', N'U') IS NOT NULL DROP TABLE dbo.#InitialData

   SELECT 1 id, 'Петров' id_chel, 'ЧП "У Васи"' mesto_raboty, CONVERT(date, '2010.10.01', 121) [data]
   INTO #InitialData
UNION ALL
   SELECT 2 id, 'Иванов' id_chel, 'ЧП "У Пети"' mesto_raboty, CONVERT(date, '2010.10.01', 121) [data]
UNION ALL
   SELECT 3 id, 'Петров' id_chel, 'ЧП "У Коли"' mesto_raboty, CONVERT(date, '2010.10.05', 121) [data]

--дата среза
DECLARE @date date = '2010.10.02'

--Требуемый запрос
SELECT DISTINCT
       t.id_chel
     , FIRST_VALUE(t.mesto_raboty) OVER (PARTITION BY t.id_chel ORDER BY t.[data] DESC) as last_mesto_raboty
     , FIRST_VALUE(t.[data]) OVER (PARTITION BY t.id_chel ORDER BY t.[data] DESC) as last_data_raboty
  FROM dbo.#InitialData AS t
WHERE t.[data] <= @date

--Удаление временной таблицы после использования
IF OBJECT_ID(N'tempdb..#InitialData', N'U') IS NOT NULL DROP TABLE dbo.#InitialData


Результат для даты 2010.10.02:
---------------------------------------------------------
id_chel | last_mesto_raboty | last_data_raboty
---------------------------------------------------------
Иванов | ЧП "У Пети" | 2010-10-01
Петров | ЧП "У Васи" | 2010-10-01



И тоже самое в другой форме:

-- с использованием CTE

--дата среза
DECLARE @date date = '2010.10.05'

;WITH
InitialData AS (
      --таблица с начальными данными
      SELECT 1 id, 'Петров' id_chel, 'ЧП "У Васи"' mesto_raboty, CONVERT(date, '2010.10.01', 121) [data] UNION ALL
      SELECT 2 id, 'Иванов' id_chel, 'ЧП "У Пети"' mesto_raboty, CONVERT(date, '2010.10.01', 121) [data] UNION ALL
      SELECT 3 id, 'Петров' id_chel, 'ЧП "У Коли"' mesto_raboty, CONVERT(date, '2010.10.05', 121) [data]
)
--Требуемый запрос
SELECT DISTINCT
       t.id_chel
     , FIRST_VALUE(t.mesto_raboty) OVER (PARTITION BY t.id_chel ORDER BY t.[data] DESC) as last_mesto_raboty
     , FIRST_VALUE(t.[data]) OVER (PARTITION BY t.id_chel ORDER BY t.[data] DESC) as last_data_raboty
  FROM dbo.#InitialData AS t
WHERE t.[data] <= @date


Результат для даты 2010.10.05:
---------------------------------------------------------
id_chel | last_mesto_raboty | last_data_raboty
---------------------------------------------------------
Иванов | ЧП "У Пети" | 2010-10-01
Петров | ЧП "У Коли" | 2010-10-05

Если, при данных исходных данных, в обоих вариантах задать дату меньше 2010-10-01, то в результате получим пустой набор данных.

Цитата(Vola @ 19.09.22, 14:50) необходимо зарегистрироваться для просмотра ссылки
SELECT DISTINCT
       t.id_chel
     , FIRST_VALUE(t.mesto_raboty) OVER (PARTITION BY t.id_chel ORDER BY t.[data] DESC) as last_mesto_raboty
     , FIRST_VALUE(t.[data]) OVER (PARTITION BY t.id_chel ORDER BY t.[data] DESC) as last_data_raboty
  FROM dbo.#InitialData AS t
WHERE t.[data] <= @date



И, конечно, тут опечатка (во втором листинге - с использованием CTE)
вместо
FROM dbo.#InitialData AS t

надо использовать
FROM InitialData AS t
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.