Arinyshka
Белый клоун, бедный мученик...
Постоялец
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
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #1 : 19-05-2008 17:41 » |
|
Если слова "по накладной" имеются везде и не встречаются в названии продукции, то достаточно в выборе подстроки 10 заменить на вызов функции поиска подстроки.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Sla
|
|
« Ответ #2 : 19-05-2008 18:25 » |
|
select SubString(Naznach,1,pos(Naznnach,"по накладной") from tables where Naznach like "%по накладной%"
что-нибудь типа такого
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #3 : 20-05-2008 06:23 » |
|
ругается 'pos' is not a recognized built-in function name.
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
Sla
|
|
« Ответ #4 : 20-05-2008 06:32 » |
|
Arinyshka, извини, чесслово не знаю как эта функция называется, должна вернуть начальную позицию подстроки
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #5 : 20-05-2008 06:34 » |
|
Пытаюсь искать... а у наших админов новый глюк и на msdn я хожу только через анонимайзер ооох
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
Sla
|
|
« Ответ #6 : 20-05-2008 06:36 » |
|
Но!!!! я хочу тебя сразу предупредить, что возможно выборка будет не совсем соответствовать желаемому Объясню Ты это вытягиваешь из, например, банковской выписки, или из какого-то другого источника Поле Назначение "набирается" руками поэтому "по накладной" != "по накладной" "по накладной" != "по нкаладной" и т.д.
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
marat_
Шеф-повар
Опытный
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
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #8 : 20-05-2008 06:45 » |
|
и я ее нашла теперь пытаюсь решить задачку дальше, буду отчитываться и вопрошать по ходу событий
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
marat_
Шеф-повар
Опытный
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
|
|
« Ответ #10 : 20-05-2008 06:50 » |
|
marat_, это какой-то извращенный способ
у меня есть подозрение что существует аналог функции поиска подстроки
Charindex ? ? ?
|
|
« Последнее редактирование: 20-05-2008 06:55 от Sla »
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
marat_
Шеф-повар
Опытный
Offline
|
|
« Ответ #11 : 20-05-2008 06:52 » |
|
Sla, я у себя в факах по сиквелу нашёл. сам с ним работал мало, просто что есть, тому и рады...
|
|
|
Записан
|
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
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_
Шеф-повар
Опытный
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
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #14 : 20-05-2008 07:27 » |
|
SQL 2005 работает, но выбирает первую же попавшуюся запись - то есть и пустую... Специально проверяла. А можно исхитриться так, чтобы первую из непустых? Я добавила ltrim(rtrim(SubString(pt.Naznach,1,PATINDEX('% по накладной%',pt.Naznach))))
в надежде, что в результате буду получать null, если до слов "по накладной" не было вбито назначения.
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
marat_
Шеф-повар
Опытный
Offline
|
|
« Ответ #15 : 20-05-2008 07:32 » |
|
а условие в запрос влепить? типа чтобы не пустая была
и поподробней, что есть пустая и что есть не пустая
|
|
|
Записан
|
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #16 : 20-05-2008 07:46 » |
|
ура, догадалась ну я и глупая, достаточно было добавить where tgp.id_Group = @id_group and ltrim(rtrim(SubString(pt.Naznach,1,PATINDEX('% по накладной%',pt.Naznach)))) !='' )
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
marat_
Шеф-повар
Опытный
Offline
|
|
« Ответ #17 : 20-05-2008 07:47 » |
|
Arinyshka, справилась с задачей?
|
|
|
Записан
|
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
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_
Шеф-повар
Опытный
Offline
|
|
« Ответ #19 : 20-05-2008 07:57 » |
|
ну получается select... where траляля = (select ... ) а то что делается циклом в языке, в сиквеле делается селектом
|
|
|
Записан
|
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
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_
Шеф-повар
Опытный
Offline
|
|
« Ответ #21 : 20-05-2008 08:08 » |
|
селект по всем строкам таблицы же идёт... извини, у тебя в коде так букв много, глаза разбегаются ты лучше конкретику гни из тгруп берём айди, его пользуем как параметр для запроса?
|
|
|
Записан
|
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #22 : 20-05-2008 08:13 » |
|
да нужно пройтись по всей тгруп и заполнить поле id_purpPay полученным для id_group результатом запроса. я и сама в шоке - такой большой запрос наваяла, и он все еще работает )
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
marat_
Шеф-повар
Опытный
Offline
|
|
« Ответ #23 : 20-05-2008 08:16 » |
|
ну значится снова вложенный запрос: select ... where id = (select id from tgroup)
|
|
|
Записан
|
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #24 : 20-05-2008 08:26 » |
|
не поняла :'( сейчас id_group запрашивается извне. Select для всей T_Group должен быть самым верхним? я могу сделать что-то вида select id_Group from T_Group
Это даст мне все записи в таблице T_Group. Для каждой из них нужно выполнить весь написанный подзапрос... Как?
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
marat_
Шеф-повар
Опытный
Offline
|
|
« Ответ #25 : 20-05-2008 08:30 » |
|
может я чего не то сказал... просто давно не работал с сиквелом и под рукой ничё нет.
попробуй всё же, в запросе где tgp.id_Group = (select id_Group from T_Group)
|
|
|
Записан
|
|
|
|
marat_
Шеф-повар
Опытный
Offline
|
|
« Ответ #26 : 20-05-2008 08:33 » |
|
в голове мелькает про псевдонимы и составные запросы, но никак не оформится
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #27 : 20-05-2008 09:14 » |
|
Arinyshka, у тебя какое-то алгоритмическое мышление SQL же - язык по сути функциональный, описывающий последовательности преобразования отношений - преобразования в реляционной алгебре. Начинать надо так: В случае запроса: select T_Group.id_Group, PurposeOfPayment.id_PurposePay ... В случае обновления: 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
Белый клоун, бедный мученик...
Постоялец
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
Белый клоун, бедный мученик...
Постоялец
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...
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
|