Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: выборка из текстовой строки неизвестной длины  (Прочитано 43127 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« : 19-05-2008 14:28 » 

Есть запрос:
Код:
CREATE PROCEDURE dbo.procedure4

@id_Group int
AS
BEGIN

SELECT DISTINCT
tgp.Name_Group,
SubString(pt.Naznach,1,10)
FROM
T_Group tgp,
T_SubGroup tsg,
T_Goods tgs,
base bs,
Treb tr,
PlatTreb pt

where
tgp.id_Group = @id_group
and
tsg.id_Group = tgp.id_Group
and
tgs.id_SubGroup = tsg.id_SubGroup
and
bs.id_goods = tgs.id_goods
and
tr.id_postavka = bs.id_postavka
and
pt.id_treb = tr.id_treb

END

Сквозь все свои and, которые у меня не получилось пока (но я пытаюсь) оформить join'ами, он выбирает строки вида:
id_Group и соответствующая ему строка pt.Naznach. Вот это:
Код:
SubString(pt.Naznach,1,10)
от отчаяния. На самом деле, строки pt.Naznach имеют вид
Код:
За кисломолочную продукцию по накладной № 073666 от
 04.09.2002 г. согласно п.4.4 договора № б/н от
17.01.2001 г.Цены договорные,в том числе НДС сумма     571  Итого с НДС 3427                                                                                                                                                                                                     
а мне из них нужно выбрать только назначение: За кисломолочную продукцию, при этом оно может быть разным, то есть по длине не получится. Нужно выбрать все от начала до "по накладной ...".

Более того, выбрав этот кусочек, мне нужно найти его в еще одной таблице и вписать вписать  в строку третьей id найденного...
Записан

Непонятная свобода обручем сдавила грудь...
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 19-05-2008 17:41 » 

Если слова "по накладной" имеются везде и не встречаются в названии продукции, то достаточно в выборе подстроки 10 заменить на вызов функции поиска подстроки.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 19-05-2008 18:25 » 

select SubString(Naznach,1,pos(Naznnach,"по накладной") from  tables
where Naznach like "%по накладной%"

что-нибудь типа такого
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #3 : 20-05-2008 06:23 » 

ругается Жаль
Код:
'pos' is not a recognized built-in function name.
Записан

Непонятная свобода обручем сдавила грудь...
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 20-05-2008 06:32 » 

Arinyshka, извини, чесслово не знаю как эта функция называется,
должна вернуть начальную позицию подстроки
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #5 : 20-05-2008 06:34 » 

Пытаюсь искать... а у наших админов новый глюк и на msdn я хожу только через анонимайзер Улыбаюсь ооох Улыбаюсь
Записан

Непонятная свобода обручем сдавила грудь...
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 20-05-2008 06:36 » 

Но!!!!
я хочу тебя сразу предупредить, что возможно выборка будет не совсем соответствовать желаемому Жаль
Объясню
Ты это вытягиваешь из, например, банковской выписки, или из какого-то другого источника
Поле Назначение "набирается" руками
поэтому
"по накладной" != "по  накладной"
"по накладной" != "по нкаладной"
и т.д.
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
marat_
Шеф-повар
Опытный

ru
Offline Offline

« Ответ #7 : 20-05-2008 06:43 » 

глянь

Функция PATINDEX имеет синтаксис:
PATINDEX ( '%образец%' , строковое_выражение )
Главное отличие этой функции от CHARINDEX заключается в том, что поисковая строка может содержать подстановочные знаки - % и _. При этом концевые знаки "%" являются обязательными. Например, использование этой функции в первом примере будет иметь вид
SELECT name FROM Ships WHERE PATINDEX('%sh%', name) > 0
А вот, например, как можно найти имена кораблей, которые содержат последовательность из трех символов, первый и последний из которых есть "e":
SELECT name FROM Ships
WHERE PATINDEX('%e_e%', name) >0
Результат выполнения этого запроса выглядит следующим образом:
name
Revenge
Royal Sovereign
Записан
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #8 : 20-05-2008 06:45 » 

и я ее нашла Улыбаюсь теперь пытаюсь решить задачку дальше, буду отчитываться и вопрошать по ходу событий Улыбаюсь
Записан

Непонятная свобода обручем сдавила грудь...
marat_
Шеф-повар
Опытный

ru
Offline Offline

« Ответ #9 : 20-05-2008 06:46 » 

а вот ещё с одного форума:

вопрос: Есть два поля, н-р: login=name1, email=name1@mail.net
нужно сделать выборку всех логинов, у которых логин равен мылу (без всего что идет за "@")
мне надо взять мыло пользователя, обрезать все что идет после @ и сравнить с логином.
подскажите пожалуйста с помощью каких функций это можно реализовать

ответ:
select ...
where login = substr(email,1,pos(email,'@'))

create function pos(v lvarchar, c lvarchar) returning int

define dummy lvarchar;
define idx int;
define len int;

let idx, len, dummy =  1, length(c), '';

while dummy != c
   let dummy, idx = substr(v, idx, len), idx + 1;
   if dummy is null then return 0; end if;
end while;

return idx-1;

end function;
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 20-05-2008 06:50 » 

marat_, это какой-то извращенный способ

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

Charindex ? ? ?
« Последнее редактирование: 20-05-2008 06:55 от Sla » Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
marat_
Шеф-повар
Опытный

ru
Offline Offline

« Ответ #11 : 20-05-2008 06:52 » 

Sla, я у себя в факах по сиквелу нашёл. сам с ним работал мало, просто что есть, тому и рады...
Записан
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #12 : 20-05-2008 07:00 » 

работает вот так:
Код:

CREATE PROCEDURE dbo.procedure4
@id_Group int
AS
BEGIN

SELECT DISTINCT
tgp.Name_Group,
SubString(pt.Naznach,1,PATINDEX('% по накладной%',pt.Naznach))
FROM
T_Group tgp,
T_SubGroup tsg,
T_Goods tgs,
base bs,
Treb tr,
PlatTreb pt

where
tgp.id_Group = @id_group
and
tsg.id_Group = tgp.id_Group
and
tgs.id_SubGroup = tsg.id_SubGroup
and
bs.id_goods = tgs.id_goods
and
tr.id_postavka = bs.id_postavka
and
pt.id_treb = tr.id_treb

END

Теперь следующий вопрос: а можно выбрать только 1, первую встретившуюся запись, даже если запрос грозится вернуть их много?
select 1
возвращает 1 столбец, насколько я поняла... а мне нужна 1 строка из множества, возвращенного запросом, непустая.
БД наполнена несколько безалаберно - запрос может вернуть несколько строк, как пустых, так и заполненных.  Мне нужно выбрать 1 непустую строку, если она существует.
« Последнее редактирование: 20-05-2008 07:08 от Arinyshka » Записан

Непонятная свобода обручем сдавила грудь...
marat_
Шеф-повар
Опытный

ru
Offline Offline

« Ответ #13 : 20-05-2008 07:13 » 

Выборка первых записей

Для SQL 2005
declare @n int
select @n=10
select top(@n) FIELD_1 from TABLE1

Для SQL 2000
declare @n int
select @n=10
set rowcount @n
select FIELD_1 from TABLE1
set rowcount 0

 
Записан
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #14 : 20-05-2008 07:27 » 

SQL 2005
работает, но выбирает первую же попавшуюся запись - то есть и пустую... Специально проверяла. А можно исхитриться так, чтобы первую из непустых?
Я добавила
Код:
ltrim(rtrim(SubString(pt.Naznach,1,PATINDEX('% по накладной%',pt.Naznach))))
в надежде, что в результате буду получать null, если до слов "по накладной" не было вбито назначения.
Записан

Непонятная свобода обручем сдавила грудь...
marat_
Шеф-повар
Опытный

ru
Offline Offline

« Ответ #15 : 20-05-2008 07:32 » 

а условие в запрос влепить? типа чтобы не пустая была

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

by
Offline Offline
Пол: Женский

« Ответ #16 : 20-05-2008 07:46 » 

ура, догадалась Улыбаюсь ну я и глупая, достаточно было добавить
Код:
where
tgp.id_Group = @id_group
and
ltrim(rtrim(SubString(pt.Naznach,1,PATINDEX('% по накладной%',pt.Naznach)))) !=''
)
Записан

Непонятная свобода обручем сдавила грудь...
marat_
Шеф-повар
Опытный

ru
Offline Offline

« Ответ #17 : 20-05-2008 07:47 » 

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

by
Offline Offline
Пол: Женский

« Ответ #18 : 20-05-2008 07:55 » 

К сожалению, это была лишь часть задачи... теперь хуже.
В результате всего произошедшего я получаю строку вида
"За кондитерские изделия", "За напитки" и тп. Без лишних пробелов, в нормализованном, так сказать, виде.
Теперь: есть таблица PurposeOfPaument вида:
Код:
CREATE TABLE [dbo].[PurposeOfPayment] (
  [id_PurposePay] int IDENTITY(1, 1) NOT NULL,

  [PurposePay] varchar(100) COLLATE SQL_Latin1_General_CP1251_CI_AS NOT NULL,


Мне по результатам уже готового селекта нужно в таблице PurposeOfPayment найти id записи PurposePay, совпадающей с выбранной. И этот id вставить в поле id_PurpPay таблицы T_Group.

сейчас я попробую возится с выборкой из PurposeOfPayment, но глобально проблема будет выглядеть так: наш выстраданный запрос работает для указанного ему id_Group, а нужно будет выполнить его махом для всей таблицы... в категориях обычного языка я бы циклом прошлась по таблице T_Group и выполнила для каждой записи наш запрос... а вот как это делается в t-sql, ума не приложу...
Записан

Непонятная свобода обручем сдавила грудь...
marat_
Шеф-повар
Опытный

ru
Offline Offline

« Ответ #19 : 20-05-2008 07:57 » 

ну получается select... where траляля = (select ... )

а то что делается циклом в языке, в сиквеле делается селектом Улыбаюсь
Записан
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #20 : 20-05-2008 08:02 » 

Код:
CREATE PROCEDURE dbo.procedure4
@id_Group int
AS
declare @n int,
@strtemp nvarchar (25)

BEGIN
select @n=1
set @strtemp = (
SELECT DISTINCT top(@n)
--tgp.Name_Group,
ltrim(rtrim(SubString(pt.Naznach,1,PATINDEX('% по накладной%',pt.Naznach))))
FROM
T_Group tgp
inner join T_SubGroup tsg on tsg.id_Group = tgp.id_Group
inner join T_Goods tgs on tgs.id_SubGroup = tsg.id_SubGroup
inner join base bs on bs.id_goods = tgs.id_goods
inner join Treb tr on tr.id_postavka = bs.id_postavka
inner join PlatTreb pt on pt.id_treb = tr.id_treb
where
tgp.id_Group = @id_group
and
ltrim(rtrim(SubString(pt.Naznach,1,PATINDEX('% по накладной%',pt.Naznach)))) !=''
)

SELECT
id_PurposePay
from
PurposeOfPayment
where
PurposePay = @strtemp

END
с этим справилась.. хотя еще надо как-то предусмотреть вариант, когда совпадения не будет.

осталось назначить эту запись полю в T_Group. Это делается через set, да? но как тогда зациклить таблицу, ведь set я выполню для конкретного поля...
Записан

Непонятная свобода обручем сдавила грудь...
marat_
Шеф-повар
Опытный

ru
Offline Offline

« Ответ #21 : 20-05-2008 08:08 » 

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

из тгруп берём айди, его пользуем как параметр для запроса?
Записан
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #22 : 20-05-2008 08:13 » 

да Улыбаюсь нужно пройтись по всей тгруп и заполнить поле id_purpPay полученным для id_group результатом запроса.

я и сама в шоке - такой большой запрос наваяла, и он все еще работает  Улыбаюсь)
Записан

Непонятная свобода обручем сдавила грудь...
marat_
Шеф-повар
Опытный

ru
Offline Offline

« Ответ #23 : 20-05-2008 08:16 » 

ну значится снова вложенный запрос:
select ... where id = (select id from tgroup)
Записан
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #24 : 20-05-2008 08:26 » 

не поняла :'(

сейчас id_group запрашивается извне.
Select для всей T_Group должен быть самым верхним?
я могу сделать что-то вида
Код:
select
id_Group
from T_Group

Это даст мне все записи в таблице  T_Group. Для каждой из них нужно выполнить весь написанный подзапрос... Как?
Записан

Непонятная свобода обручем сдавила грудь...
marat_
Шеф-повар
Опытный

ru
Offline Offline

« Ответ #25 : 20-05-2008 08:30 » 

может я чего не то сказал... просто давно не работал с сиквелом и под рукой ничё нет.

попробуй всё же, в запросе где tgp.id_Group = (select id_Group from T_Group)
Записан
marat_
Шеф-повар
Опытный

ru
Offline Offline

« Ответ #26 : 20-05-2008 08:33 » 

в голове мелькает про псевдонимы и составные запросы, но никак не оформится
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #27 : 20-05-2008 09:14 » 

Arinyshka, у тебя какое-то алгоритмическое мышление Улыбаюсь SQL же - язык по сути функциональный, описывающий последовательности преобразования отношений - преобразования в реляционной алгебре.

Начинать надо так:

В случае запроса:
Код: (Text)
select
   T_Group.id_Group,
   PurposeOfPayment.id_PurposePay
...

В случае обновления:
Код: (Text)
update T_Group
set id_purpPay = PurposeOfPayment.id_PurposePay
...

Я многоточия раскрыть не могу, поскольку не знаю, как связаны записи T_Group и PurposeOfPayment для запроса, или какие записи в T_Group нужно обновлять конкретной записью PurposeOfPayment.

Эту информацию нужно получить. Затем просто подставить во "from" необходимые таблицы или подзапросы.

Кроме того, я не вполне понял, что нужно сделать: в таблице групп обновить ID или получить выборку, где бы в одной строке сочеталась информация о группе с информацией из PurposeOfPayment.
« Последнее редактирование: 20-05-2008 09:16 от dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #28 : 20-05-2008 11:10 » 

Arinyshka, у тебя какое-то алгоритмическое мышление Улыбаюсь
Спасибо Улыбаюсь я уж давно стала бояться, что мышление у меня просто отсутствует, а тут такой комплимент... расплываюсь в улыбке  Скромно так...
в таблице групп обновить ID
Именно. В таблице T_Group нужно обновить поле id_PurpPay. Уже получилось вычислить значение этого поля, осталось только его туда поместить... Сейчас споткнулась на следующем: пытаюсь уговорить функцию вместо null возвращать некоторое фиксированное значение. Но...
Код:
set @tempId =(
SELECT
id_PurposePay
from
PurposeOfPayment
where
PurposePay = @strtemp)


if @tempId = null set @tempId = 41

все равно возвращает null, если не находит поля.... почему не 41???
Записан

Непонятная свобода обручем сдавила грудь...
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #29 : 20-05-2008 11:16 » 

ооо! Помогла вот такая конструкция:
Код:
if EXISTS
    (SELECT id_PurposePay
     from PurposeOfPayment
     where PurposePay = @strtemp)
begin
  set @tempId =(SELECT id_PurposePay
                             from PurposeOfPayment
                             where PurposePay = @strtemp)
end

else
set @tempId = 41
Убейте меня, если я понимаю, почему не работал if...
Записан

Непонятная свобода обручем сдавила грудь...
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines