Имя: Пароль:
IT
Админ
Подскажите по запросу SQL
0 bublegum
 
29.11.13
10:47
Есть запрос, для простоты вот такой, например:

SELECT table.text
FROM table

Нужно добавить вычисление длины самой длинной выбранной строки.
Как это сделать лучше всего?
Предполагаю, нужно использовать
max( CHAR_LENGTH( table.text ) )
Но как это использовать в запросе?
1 КонецЦикла
 
29.11.13
10:58
SELECT TOP 10 LEN(date_time_iddoc) AS Length
FROM _1sjourn (NOLOCK)
2 bublegum
 
29.11.13
11:06
(1) Похоже твой вариант обрежет таблицу и выберет только TOP 10 записей, и остальные выбранные записи пропадут, придется второй выборкой их выбирать, а это наверное плохо.
3 viktor_vv
 
29.11.13
11:08
Так тебе надо выбрать одну строку с макисмальной длиной реквизита, или как ?
4 КонецЦикла
 
29.11.13
11:09
(2) SELECT Len(table.text)
FROM table

Так пойдет?

Написал Top на случай если кто-то полезет выполнять :)
5 viktor_vv
 
29.11.13
11:11
Расшифруй на пальцах вот это

"вычисление длины самой длинной выбранной строки".
6 bublegum
 
29.11.13
11:11
(3) мне надо добавить вычисление самой длинной строки в существующий запрос, при этом не портя этот запрос. Изначально запрос выбирает много строк.
7 Ненавижу 1С
 
гуру
29.11.13
11:12
(6) что на выходе то должно быть?
8 viktor_vv
 
29.11.13
11:12
(6) В каком виде нужен результат вычисления "Самой длиной строки" ?
9 КонецЦикла
 
29.11.13
11:14
А сорри, ну тогда так пойдет?

SELECT Max(LEN(Text)) AS Length
FROM Table(NOLOCK)
10 bublegum
 
29.11.13
11:15
(5) предположим запрос дает такой результат:

table.text:
"вавыы"
"йцуйц кйцкйц"
"выывпы"

А мне нужно чтобы он еще вычислил длину строк, определил самую длинную, и выдал это число хоть как-нибудь, например в отдельной колонке:

table.text,       table.length
"вавыы", 12
"йцуйц кйцкйц", 12
"выывпы", 12
11 bublegum
 
29.11.13
11:16
(9) так вообще выберется всего одна строка.
12 КонецЦикла
 
29.11.13
11:19
Ясно. Через 10 постов.
Так пойдет?

SELECT Text, LEN(Text) AS Length
FROM Table(NOLOCK)
order by LEN(Text) Desc
13 toypaul
 
гуру
29.11.13
11:20
(12) как я понял - надо в каждой строке макс длину по всей таблице
14 КонецЦикла
 
29.11.13
11:20
Я пока отчаливаю...
15 toypaul
 
гуру
29.11.13
11:21
что-то типа этого

select t.f,l.l from t,(select max(len(t.f)) l from t) l
16 bublegum
 
29.11.13
11:22
(12) нет, так ты испортил всю сортировку в таблице тем что вставил order by LEN(Text) Desc
17 bublegum
 
29.11.13
11:23
(15) то есть два раза делать выборку по таблице. Не красиво как-то...
18 toypaul
 
гуру
29.11.13
11:24
(17) сделай красиво
19 Ёпрст
 
29.11.13
11:30
(17) ежели скуль >=2008 то пользуй over
20 Ёпрст
 
29.11.13
11:30
там будет красиво и одним запросом
21 viktor_vv
 
29.11.13
11:30
(17) Зато логично :).
22 Ёпрст
 
29.11.13
11:31
только не помню, был ли over в 2005..
23 КонецЦикла
 
29.11.13
11:39
(16) Ой...
А может ты подключишься к обсуждению хотя бы живым понятным примером наподобие (10)?
24 bublegum
 
29.11.13
11:40
over похоже нет. У меня вообще MySQL
(23) а чем пример из (10) не подходит?
25 Ёпрст
 
29.11.13
11:42
в MySQL не в курсе, есть ли там ранжирующие функции
26 bublegum
 
29.11.13
11:42
Наверное лучше всего использовать временную таблицу, поместить в нее всю выборку, а потом уже во временной таблице считать максимальную длину строки.
27 Ёпрст
 
29.11.13
11:44
тогда так
select t.f,(select max(len(f)) from t (nolock))
from t (nolock)
28 Ёпрст
 
29.11.13
11:45
Коррелированный подзапрос будет выполнятся 1 раз, если че..
29 IVT_2009
 
29.11.13
11:46
SELECT len(str) AS ln FROM table ORDER BY ln DESC LIMIT 10
30 IVT_2009
 
29.11.13
11:47
удаляет по ID где менее 10 записей

DELETE FROM coord WHERE id
in(SELECT id FROM (SELECT id,count(id) as dd FROM coord GROUP BY id ) WHERE dd<10);
31 toypaul
 
гуру
29.11.13
11:50
(17) вообще головой надо думать. как можно за один проход получить серверу нужный результат? всеравно первой выборкой обходим все строки чтобы определить максимум, второй выборокой получаем результат.

если исходная таблица это сложный запрос, то конечно лучше его во врем таблицу скинуть.
32 КонецЦикла
 
29.11.13
11:50
(26) А потом делать селект из временной таблицы? См (28)
33 bublegum
 
29.11.13
11:51
(27) это же все равно два запроса. разве нет?
34 КонецЦикла
 
29.11.13
11:51
(33) Храни где-нибудь максимальную длину, делов-то
35 bublegum
 
29.11.13
11:52
получается запрос + подзапрос, запрос выбирает все данные, подзапрос выбирает те же самые данные + находит длину самой длинной строки
36 Ёпрст
 
29.11.13
11:53
(33) и че ?
37 Ёпрст
 
29.11.13
11:53
ты разницу в скорости для миллиона записей даже не заметишь
38 dk
 
29.11.13
11:54
(27) +1
39 bublegum
 
29.11.13
11:54
(36) не красиво же.
40 madyka
 
29.11.13
11:54
declare
    @MaxLen Int;
Set @MaxLen = (Select max(len(t.text)) from table as t(nolock))

Select
     t.text as Str,
     @MaxLen as MaxLen
from table (nolock)
41 КонецЦикла
 
29.11.13
11:54
1С делает также некоторые вещи, подзапросом
Так что тебе тоже можно
42 IVT_2009
 
29.11.13
11:55
(40) красиво ms sql умеет
43 bublegum
 
29.11.13
11:56
(34) например где ее хранить? Думаю было бы оптимально пробежаться по таблице во время выборки данных один раз, считать длину текущей строки, сравнивать ее с максимальной, и если она больше, то далее считать ее максимальной. И чтобы результат получился такой:

table.text,     table.length
"вавыы",        5
"йцуйц кйцкйц", 12
"выывпы",       12

тогда я буду знать что в последней строке находится нужный результат.
44 bublegum
 
29.11.13
11:58
(40) тоже два раза выбираются данные
45 КонецЦикла
 
29.11.13
11:59
(43) Триггер навесь и храни где-нибудь
Если выборка выполняется миллион раз в день то будет оправданно
46 madyka
 
29.11.13
11:59
(37)

записей 175 млн строк. один запрос с выражением потребует группировку. Опять же лишнее...

Так что только с подзапросом - вычислить макс длину. И вставлять куда нужно
47 bublegum
 
29.11.13
11:59
(43) Это я знаю как сделать только в цикле, когда уже данные выбраны. Как заставить это сделать запросом я не знаю (((
48 madyka
 
29.11.13
12:00
(44)
Чем те не нравится 2 раза?
49 КонецЦикла
 
29.11.13
12:01
(47) Триггер который будет сравнивать длину вставляемой/редактируемой строки и хранимую где-нибудь длину (сам выбери базу и таблицу создай). Вот и все.
50 bublegum
 
29.11.13
12:01
(48) Думаю что 1 раз лучше чем 2. Более логично. Данные и условия абсолютно одинаковые выбираются, зачем два раза их выбирать?
51 bublegum
 
29.11.13
12:02
(49) условия выборки каждый раз разные. Я упростил запрос только для примера, чтобы не пугались.
52 madyka
 
29.11.13
12:04
(50)
Не всегда.

Если же тебе постоянно надо знать актуальное значение максимального значения длины строки - то советую триггер.
Будет быстрее использоваться в дальнейшем, особенно если к-во строк в таблице на десятки сотни млн строк. А если колонка текстовая длиной в 100 букв и больше - то тем более.
53 madyka
 
29.11.13
12:05
(0) - (49) уже писал
54 madyka
 
29.11.13
12:05
"Логично" - не всегда самый короткий и быстрый путь
55 madyka
 
29.11.13
12:07
Вот у мну запрос с выражением занял 4 мин, и вариант с двумя запросами - 2 мин.
56 madyka
 
29.11.13
12:12
Причем, если колонка, по которой идет подсчет макс длины, типа char - то придется добавить RTRIM (отсечь правые пробелы), иначе макс длина будет равна длине строки колонки
57 madyka
 
29.11.13
12:13
а строковые операции довольно тормозят.
ТАк что настоятельно рекомендую, как другие говорили - триггер и хранить макс длину в любом месте базы.
Эти при условии частого использования этой величины.
58 КонецЦикла
 
29.11.13
12:18
(56) у тебя SQL какой-то неправильный, не нужно отсекать
59 Jaap Vduul
 
29.11.13
12:20
(43)
Насколько помню, в mysql можно так:
set @max=0;
select table.text, @max:=IF(CHAR_LENGTH(table.text)>@max,CHAR_LENGTH(table.text),@max) from table
60 bublegum
 
29.11.13
12:26
(59) о, супер! Если так можно...
61 КонецЦикла
 
29.11.13
12:28
(60) Все равно это скан таблицы, посмотри планы выполнения
Чудес не бывает
Храни значение если его нужно получать быстро
62 madyka
 
29.11.13
12:31
(59) - выражение вычисляется походу 2 раза
И максимальное значение будет не во всех строках, а к концу таблицы. Не оч хорошо.
63 GANR
 
29.11.13
12:31
(0) Рассмотрим несколько возможных ситуаций:

1. Если дело на МС СКЛ 2012

select a.text, max(len(a.text)) over() max_len from table a

2. Если более молодая версия - запросик будет малость посложнее

select a.text, b.max_len from
table a, (select max(len(a.text)) max_len from table a) b

3. Если непонятно вышесказанное в этом сообщении - идем сюда http://www.sql-ex.ru/.
64 bublegum
 
29.11.13
12:32
Все понятно, только (59) пока лучше всех
65 Ёпрст
 
29.11.13
12:33
(63) over есть и на 2008, у автора - мускул..
66 Ёпрст
 
29.11.13
12:34
(64) чем ?
Ты хоть ЭТО проверил ?
:))
67 madyka
 
29.11.13
12:35
(64) - ты попробуй блин сначала на сервере, а потом уже говори у кого лучше :)
Опять же повторюсь - если таблица в десятки млн строк - то как ни крути - запрос будет "думать"...
68 КонецЦикла
 
29.11.13
12:36
(66) Да, автор похож на упоротого "начальнега"
69 GANR
 
29.11.13
12:38
(64) А что именно лучше - ответит план запроса.
(65) Нееет - с 2005 были ранжирующие функции, а вот в 2012-м появились именно оконные - это немного разные вещи http://www.sql-tutorial.ru/ru/book_window_functions.html
http://www.sql-tutorial.ru/ru/book_running_totals/page2.html.
70 bublegum
 
29.11.13
12:40
(66) тем что ничего лишнего не выбирается.
71 bublegum
 
29.11.13
12:40
(67) На сервере работает отлично
72 GANR
 
29.11.13
12:43
А как такая версия для мускула?

select a.name, b.max_len from
ships a, (select max(char_len(a.name)) max_len from ships a) b
73 GANR
 
29.11.13
12:46
select a.text, b.max_len from
table a, (select max(char_len(a.text)) max_len from table a) b
74 Ёпрст
 
29.11.13
12:46
(69) нифига, с 2008
75 madyka
 
29.11.13
12:48
(58)
Гм, каюсь, ты прав - отсекать пробелы предварительно не нужно, len пробелы не учитывает справа )
76 GANR
 
29.11.13
12:48
77 madyka
 
29.11.13
12:49
(71)
Опробуй несколько запросов, и только после этого делай выводы.
Кому хорошо - другому смерть.
78 GANR
 
29.11.13
12:49
(76) к (74)
79 GANR
 
29.11.13
12:53
+(76)(74) Ах воооон как - точно, это было до 2012, только без секции order by, что не позволяло именно накопительный итог считать.
80 Ёпрст
 
29.11.13
12:59
(76) ну и че ты 2005 подсовываешь ?
Я грю за 2008
81 Ёпрст
 
29.11.13
12:59
(79) в 2008 позволяло.
82 Ёпрст
 
29.11.13
13:01
посмотри примеры с мах, мин, суммой.. для каждой строки..
83 GANR
 
29.11.13
13:36
(81) И в 2005 и в 2008 была секция PARTITION BY для (82), а вот в 2012 появилась еще и секция ORDER BY для оконных функций http://msdn.microsoft.com/ru-ru/library/ms189461(v=sql.100).aspx - вот она и позволила считать накопительные итоги (не по этой задаче).
84 GANR
 
29.11.13
13:37
85 КонецЦикла
 
29.11.13
13:41
Епать, целый диспут развернулся
86 Ёпрст
 
29.11.13
13:56
(83) ты про фифо прям в запросе что ле ?..
87 Ёпрст
 
29.11.13
13:57
надо будет посмотреть..
88 GANR
 
29.11.13
13:58
(86) И это в частности.
89 GANR
 
29.11.13
14:00
+(88) Но если (86) делать 1С-овским запросом - эдак, имхо, сервер уронить можно.
90 Sorm
 
29.11.13
14:24
(89) Надо будет посмотреть, во что транслируется фифо из 1с, я делал в скуле прямо - все чисто, красиво.
91 GANR
 
29.11.13
15:30
(90) Оконные функции и функции ранжирования нельзя использовать на уровне 1С-запросов - вот и подумай после этого что будет в скуле.