Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Получить два поля из параметра

16K
08 апреля 2011 года
MAcK
54 / / 09.06.2008
есть статья которая показывает как получить поле с Ид из параметра. Но мне нужно получить два поля с ИД. Уже третий день мучаюсь.

 
Код:
CREATE FUNCTION inline_split_me (@param varchar(7998)) RETURNS TABLE AS
   RETURN(SELECT substring(',' + @param + ',', Number + 1,
                    charindex(',', ',' + @param + ',', Number + 1) - Number - 1)
                 AS Value
          FROM   Numbers
          WHERE  Number <= len(',' + @param + ',') - 1
            AND  substring(',' + @param + ',', Number, 1) = ',')


Как сделать, чтобы получить значения в два поля.
пример: inline_split_me('9, 12, 27, 38, 44, 55, 66, 77')
Поле1 | Поле2
9 | 12
27 | 38
44 | 55
66 | 77
412
08 апреля 2011 года
grgdvo
323 / / 04.07.2007
Какая СУБД?
если postgres, может это частично поможет
16K
08 апреля 2011 года
MAcK
54 / / 09.06.2008
MSSQL server 2000
385
08 апреля 2011 года
SomewherSomehow
477 / / 25.07.2004
я вам уже приводил решение на другом формуе (правда под 2005 сиквел, т.к. вы ни словом не обмолвились что у вас 2000).
тогда здесь приведу под 2000.
Код:
declare @param varchar(7998)
set @param = '8, 9, 27, 38, 44, 55, 66, 77'

--1. Способ номер раз (с временной таблицей)
declare @t table (id int identity, pole int)
insert into @t(pole)
SELECT
    val = convert(int,substring(',' + @param + ',',Number + 1,charindex(',', ',' + @param + ',', Number + 1) - Number - 1))
FROM  
    Numbers
WHERE  
    Number <= len(',' + @param + ',') - 1 AND  substring(',' + @param + ',', Number, 1) = ','

select
    pole1 = max(pole1),
    pole2 = max(pole2)
from
(
    select
        rn = id%2,
        gr = id%2+id,
        pole1 = (case when id%2 = 1 then pole else null end),
        pole2 = (case when id%2 = 0 then pole else null end)
    from
        @t
) t
group by
    gr
--2. Способ номер два-с (в один запрос) // achtung govnokod detected!
select
    pole1 = max(pole1),
    pole2 = max(pole2)
from

(
    select
        t1.id,
        pole1 = (case when count(*)%2 = 1 then t1.pole else null end),
        pole2 = (case when count(*)%2 = 0 then t1.pole else null end),
        rn = count(*)%2,
        gr = count(*)%2+count(*)
    from
        (
            SELECT
                id = number,
                pole = convert(int,substring(',' + @param + ',',Number + 1,charindex(',', ',' + @param + ',', Number + 1) - Number - 1))
            FROM  
                Numbers
            WHERE  
                Number <= len(',' + @param + ',') - 1 AND  substring(',' + @param + ',', Number, 1) = ','
        ) t1
        left join
        (
            SELECT
                id = number,
                pole = convert(int,substring(',' + @param + ',',Number + 1,charindex(',', ',' + @param + ',', Number + 1) - Number - 1))
            FROM  
                Numbers
            WHERE  
                Number <= len(',' + @param + ',') - 1 AND  substring(',' + @param + ',', Number, 1) = ','
        ) t2 on t1.id >= t2.id
    group by
        t1.id,
        t1.pole
) t
group by
    gr

второй способ не рекомендую, первый быстрее и красивее.
есть еще третий способ - это парсить по два значения, и кейсом вытаскивать по разным полям, можете тож попробовать.
16K
09 апреля 2011 года
MAcK
54 / / 09.06.2008
Спасибо, всё работает.
Теперь вопрос в другом. Возможно ли сделать следующее:
есть два параметра: первый - ид, второй количество записей. У нас есть массив параметров: ('0001,2,0002,2,0003,5').
Теперь нужно получить 2 -е записи для ид =0001, столько же для ид=0002 и пять для ид=0003.
Подскажите в какую сторону копать?
385
09 апреля 2011 года
SomewherSomehow
477 / / 25.07.2004
Т.е. задвоить, затроить и т.д. записи в зависимости от значения параметра?
вот так можно
Код:
declare @param varchar(7998)
set @param = '0001,2,0002,2,0003,5'

--1. Способ номер раз (с временной таблицей)
declare @t table (id int identity, pole int)
insert into @t(pole)
SELECT
    val = convert(int,substring(',' + @param + ',',Number + 1,charindex(',', ',' + @param + ',', Number + 1) - Number - 1))
FROM  
    Numbers
WHERE  
    Number <= len(',' + @param + ',') - 1 AND  substring(',' + @param + ',', Number, 1) = ','

-- результат парсинга таблицы запишу во временную таблицу
-- для наглядности "задваивающего" запроса на практике
-- можно просто юзать поздапроз, без временной таблицы
declare @parsed table (a int, b int)
insert into @parsed(a,b)
select
    pole1 = max(pole1),
    pole2 = max(pole2)
from
(
    select
        rn = id%2,
        gr = id%2+id,
        pole1 = (case when id%2 = 1 then pole else null end),
        pole2 = (case when id%2 = 0 then pole else null end)
    from
        @t
) t
group by
    gr
-- "задваивающий" запрос
select *
from
    @parsed p
    join Numbers n on p.b >= n.Number
16K
09 апреля 2011 года
MAcK
54 / / 09.06.2008
Нет. есть данные:
0001, 1, 125.25
0001, 2, 225.25
0001, 3, 325.25
0001, 4, 425.25
0001, 5, 525.25
0002, 1, 11.11
0002, 2, 121.11
0002, 3, 131.11
0002, 4, 141.11
0002, 5, 151.11

и если я указываю (0001, 2, 1, 0002,3, 3), то я получаю данные
0001, 2, 225.25
0002, 3, 131.11
0002, 4, 141.11
0002, 5, 151.11

где в списке:
1. 0001 - ИД клиента
2. 2 - идентификатор identity(1, 1)
3. 1 - количество записей начиная с идентификатора 2

для второго аккаунта будем брать 3 записи начиная с идентификатора 3
385
09 апреля 2011 года
SomewherSomehow
477 / / 25.07.2004
Цитата: MAcK
Нет. есть данные:
0001, 1, 125.25
0001, 2, 225.25
0001, 3, 325.25
0001, 4, 425.25
0001, 5, 525.25
0002, 1, 11.11
0002, 2, 121.11
0002, 3, 131.11
0002, 4, 141.11
0002, 5, 151.11

и если я указываю (0001, 2, 1, 0002,3, 3), то я получаю данные
0001, 2, 225.25
0002, 3, 131.11
0002, 4, 141.11
0002, 5, 151.11

где в списке:
1. 0001 - ИД клиента
2. 2 - идентификатор identity(1, 1)
3. 1 - количество записей начиная с идентификатора 2

для второго аккаунта будем брать 3 записи начиная с идентификатора 3


Какие данные?? Они реально так хранятся или это результат тех запроосв что я привел?? Или эти запросы призваны лишь для того чтобы распарсить параметры???

Давайте тогда оглашать всю задачу сразу целиком?! Потому как вы выдаете задачу порциями и это не лучшим образом сказывается на продуктивности и моих ответов и моем времени, и ваших вопросов и вашем времени соответственно. Т.к. когда задачу виднов целом - можно сформировать более эффективно решение.
Мне непонятно - что вам надо в итоге и какие данные у вас есть?
Для того чтобы правильно задавать вопросы потрудитесь почитать правила постинга в раздел
Кроме этого предоставьте:
1) исходные данные: скрипты создания тестовых таблиц и заполнения их тестовыми данными
2) подробное описание задачи: как вы работаете с данными, эдхок запросы, хранимые процедуры или функции? какие параметры, какие они могут иметь значения и т.д.
3) желаемый результат
Без этого - переливаем из пустого в порожнее.

10
10 апреля 2011 года
Freeman
3.2K / / 06.03.2004
Цитата: MAcK
будем брать 3 записи начиная с идентификатора 3


Задача на аналитические функции с "окнами".

SomewherSomehow, в MS SQL аналитические функции вроде уже есть, а есть ли оконные выражения (rows between unbounded preceding and unbounded following)?

385
10 апреля 2011 года
SomewherSomehow
477 / / 25.07.2004
Цитата: Freeman
Задача на аналитические функции с "окнами".

SomewherSomehow, в MS SQL аналитические функции вроде уже есть, а есть ли оконные выражения (rows between unbounded preceding and unbounded following)?



Не вроде, а точно есть. Просто если вы внимательно прочтете топик то увидите что у автора 2000 сиквел =( там нет аналит.функций.

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

16K
10 апреля 2011 года
MAcK
54 / / 09.06.2008
Цитата:
Давайте тогда оглашать всю задачу сразу целиком?!


Задача с двумя параметрами была полная. Просто появилась новая, подобная первой.

Цитата:
И конечно эти порции только все портят, что я и пытаюсь донести до автора...


Я понимаю ...
В скрипте есть функция, переделанная для трёх полей.
что нужно получить при данном параметре: ('00010,0056,3,00020,0082,2,00050,0160,2)

Три записи для Acct = 00010, начиная с Num = 0056. То есть (0056, 0057, 0058)
две записи для Acct = 00020, c Num = 0082, 0083.
две записи для Acct = 00050, Num = 0160, 0161.

Примечание. Записи в оригинале не отсортированы. Нужно брать следующую запись для определённого аккаунта, просто отсортировать по Num (Order by Acct, Num), так как записи могу быть удалены и следующий Num уже будет другой.
если удалить запись Acct = 00010, Num = 0057б то берём записи 0056,0058,0059.

Что ещё нужно для решения?

385
11 апреля 2011 года
SomewherSomehow
477 / / 25.07.2004
Более менее понятно, т.е. нужна функция, в которую передается строка. Данная стркоа делится на три части. В каждой части указано для какого Acct, начиная с какого Num, сколько записей брать - так?
Тогда еще один вопрос, формат строки ('00010,0056,3,00020,0082,2,00050,0160,2') - вы задаете? если вы, то для простоты и скорости был бы удобен например такой формат: '[00010].[0056].[3],[00020].[0082].[2],[00050].[0160].[2]'
385
11 апреля 2011 года
SomewherSomehow
477 / / 25.07.2004
вот вам с таким форматом строки, просто так действительно быстрее и красивее
1. функция
Код:
create function dbo.uf_ParseBDebitQueryParams(@param varchar(8000))
returns table
as
return
(
    select
        Acct = parsename(p.val,3),
        Num = parsename(p.val,2),
        quant = convert(int, parsename(p.val,1))
    from
        (
            select
                val = substring(',' + @param + ',',Number + 1,charindex(',', ',' + @param + ',', Number + 1) - Number - 1)
            from
                Numbers
            where
                Number <= len(',' + @param + ',') - 1 AND  substring(',' + @param + ',', Number, 1) = ','
        ) p
)

2. запрос
Код:
declare @param varchar(7998)
set @param ='[00010].[0056].[3],[00020].[0082].[2],[00050].[0160].[2]'
       
select *
from
(
    select
        rn = (
            select count(*)
            from
                [B_Debit] dn
            where
                dn.Acct = d.Acct and
                dn.Num <= d.Num and
                dn.Num >= p.Num        
        ),
        p.quant,
        d.*    
    from
        [B_Debit] d
        join dbo.uf_ParseBDebitQueryParams(@param) p on p.Acct = d.Acct and d.Num >= p.Num
) q
where
    q.rn <= q.quant

пару примеров прогнал - работает, но тщательно не тестировал, это вы уж сами.
16K
11 апреля 2011 года
MAcK
54 / / 09.06.2008
Спасибо. Протестирую :)
16K
19 апреля 2011 года
MAcK
54 / / 09.06.2008
Работает медленно. ~2 сек. 350 милисек. При том что я выкинул теритй параметр, оставив только
 
Код:
Select d.* -- тут указывал имя полей    
    from
        [B_Debit] d
        join dbo.uf_ParseBDebitQueryParams(@param) p on p.Acct = d.Acct and d.Num >= p.Num


Ваш же перыдущий код для двух полей ('1234,011') работает быстрее: ~020 милисек.
Была сделана выборка для 121 записи.
385
19 апреля 2011 года
SomewherSomehow
477 / / 25.07.2004
У меня для 10 тыс. записей заняло 122 мс. Т.е. как я и говорил, довольно быстро.
Так что смотрите, что вы там еще делаете.
Изучайте планы. Возможно в вашей ситуации оптимизатор выбирает какой-то неудачный план.
16K
20 апреля 2011 года
MAcK
54 / / 09.06.2008
Цитата: SomewherSomehow
У меня для 10 тыс. записей заняло 122 мс.


Я тестировал с 212К записями. проблему решил, убрав Quantity, так как в производительности это не выигрывает

385
20 апреля 2011 года
SomewherSomehow
477 / / 25.07.2004
А, так у вас не 121 запись, а 212 тысяч? и еще при довольно широкой таблице...тогда две секнды вполне нормальная скорость, учитывая что для каждой из двуста тысяч записей отрабатывает подзапрос на номер ряда.
Переходите уже на более новую версию, там есть оконные функции типа row_number() т.д. - будет быстрее.
16K
20 апреля 2011 года
MAcK
54 / / 09.06.2008
Цитата:
Переходите уже на более новую версию, там есть оконные функции типа row_number() т.д. - будет быстрее.


Не могу перейти. Не в моей компетенции. Оставил без quantity.
Спасибо за помощь

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог