Как стать автором
Обновить

Комментарии 94

Что-то отступы у меня не получаются(

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

я привык, что всегда строка начинается с ключевого слова (подобно FROM или ORDER BY), а группировка основных секций-блоков идет с помощью отсутпов. + ON не выделяется отдельно а идет вместе с JOIN (ибо неразрывно с ним связан), т.е. мой вариант такой:

SELECT
	t.field,
	t.field1,
	...
FROM tbl t
	INNER JOIN table1 t1	ON t1.id=t.id
	INNER JOIN table2 t2	ON t2.id=t1.id
WHERE 1=1
	AND t.value='foo'
	AND t1.value='bar'
GROUP BY t.field
ORDER BY t.field

Но не навязываю и ни к чему призываю, само собой..., дело вкуса :)
я тоже такой использую.
Именно так.
Я тоже так думаю. Топик на самом деле ни о чем. Все сразу начинают меряться длинной и писать как они форматируют запросы.

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

О стандартах кодирования написано уже очень много, на самом деле на всех фирмах которые я работал. Мне перед началом работы давали время с ними ознакомиться и писать в указанном стиле.

Хотя я пишу запросы в таком же стиле как и вы.
*… на всех фирмах, на которых я работал.
Мне наверно повезло (или наоборот) — но я не прочитал ни одного документа, посвященного стандартам кодирования, и ни разу не попал в команду с устоявшимися стандартами, так что мои вкусы — результат личной практики, ну и что-то где-то бессознательно впитал на чужих примерах :)

Для запросов без форматирования есть несколько причин — тут не очень дружелюбный парсер, имхо. Понять как он работает, и что и когда выкусывает — можно только после некоторой практики, но после пары использований лично у меня было желание им больше не пользоваться. К тому же о том, что тут есть такие возможности лично я как то даже и не сразу заметил (+где то вроде натыкался, что html-тэги доступны только выше некоторого количества кармы, может ошибаюсь).
Ну и потом наверно многим лень этим заниматься.

Кстати не все запросы требуют форматирования. Запросы вида «SELECT name FROM obj_types» я, например, часто так и пишу в одну строку, ибо они слишком просты.
Не знаю, я пользовался всезда Source Code Highlighter-ом, меня вполне удовлетворяло всегда как он подсвечивает и представляет в хтмл мои SQL запросы.

Да, вы правы короткие запросы я тоде не форматирую. В этом нет смысла. Но нечто подобное
habrahabr.ru/blogs/mysql/46068/#comment_1171518
Тут уж без форматирования никак. (Дал ссылку на запрос даже не смотря что это за запрос, просто ориентируясь на размер)
И я так.
Поддерживаю
точно так )
НЛО прилетело и опубликовало эту надпись здесь
Насчёт регистра — пишу на PHP, и строки подсвечиваются исключительно как строки, одним цветом =)
Поэтому, всё-таки, удобнее, когда ключевые слова в верхнем регистре
Ваш способ благословлен настоятелем.
вариант 2, но с
WHERE '
t.value='foo'
AND
t1.value='bar'
пробелы сьело
WHERE 
    t.value='foo'
    AND 
    t1.value='bar'
Поддерживаю этот вариант
присоединяюсь
Второй вариант, на мой взгляд, более удобоваримый, чем первый.
Даже при беглом взгляде, видно какое действие в какой строчке выполняется.
второе. потому что так более читабельно для людей, которые будут читать после меня. Но это мое мнение, что большинство программистов делает так =)
Я бы проверил таким образом: вбил бы запрос в phpmyadmin и посмотрел как он его на выходе отформатирует.
К сожалению, для оппонента phpMyAdmin — не аргумент=)
* вбил для проверки, форматирует примерно так же, как предложил maxshopen

=) То есть — phpMyAdmin за второй вариант=)
Того, кто поставил минус сейчас забаню.
я использую первый вариант.
Надо было сделать топик-опрос. Результаты были бы нагляднее.
Тогда не поместились бы примеры туда(
Тема вложенных запросов не раскрыта, вот там уж точно читабельность необходима.
Мы не используем вложенные запросы в селектах)
А другие люди используют. Все зависит от задачи.
А в чем собственно проблема, следуем тем же принципам:

SELECT
  t.field,
  t.field1,
  ...
FROM 
  ( SELECT
      t_in.field,
      t_in.field1,
      ...
    FROM t_in
    WHERE t_in.id = 100
    GROUP BY t.field
    ORDER BY t.field
  ) AS tbl_in
  INNER JOIN table1 t1 ON t1.id=t.id
  INNER JOIN table2 t2 ON t2.id=t1.id
WHERE 1=1
  AND t.value='foo'
  AND t1.value='bar'
GROUP BY t.field
ORDER BY t.field


К сожалению tab внутри pre разносит сильно вширь, поэтому поменял на nbsp, в редакторе удобнее конечно использовать табуляцию (хотя обять же это дело вкуса)
смысл самого запроса нулевой — только для демки форматирования.

расскажите смысл «1=1», плз
Тут же пример, а не реальные запросы

нет в нём смысла никакого, очевидно
что бы все реальные условия начинались одинаково — с AND. Сам так часто делаю.
Человеку хочется, чтобы условия с новой строчки пошли, но без 1=1 исключается один AND, пропадает форматирование одинаковое для всех условий.
Я бы просто после AND на каждой строчке ставил бы TAB и первую строчку соответственно оттабил, т.е. примерно так:
WHERE
        t.value='foo'
  AND   t1.value='bar'

Здесь пробелы, а не табы, для наглядности.
Кому по душе форматирование пробелами, соответственно, может и пробелами так выровнять.
Ну во первых, как уже сказали — для красоты :)
Но это не самое главное. Представьте себе ситацию, у нас есть функиция, в которой запрос генерится исходя из переданных ей параметров, например (опять же пример от балды, только для демонстрации)

SELECT ... FROM ...
WHERE
if(def condition1){	f1='condition1'	}
if(def condition2){	f2='condition2'	}

тут видно, что будет ошибка, т.к. в момент первой проверки, мы не знаем результат второй, и поэтому не можем поставит AND после нее. Во стором условии мы не знаем результат первого, поэтому не можем поставить вначале. Более того, если не выполится ни одно их них — то мы получим ошибку синтаксиса из-за пустого WHERE. Эти проблемы можно решить кучей дополнительных if-ов, количество и громоздкость которых будет увеличиваться от количества условий. А можем решить по простому:

SELECT ... FROM ...
WHERE 1=1
if(def condition1){	AND f1='condition1'	}
if(def condition2){	AND f2='condition2'	}


Тут никаких доп. проверок делать не надо, и если не будет задано ни одного условия, то ошибки тоже не произойдет. Причем если мы уже сгенерированный запрос кладем для анализа в лог — то там мы увидим вполне красиво отформатированный запрос. Что же касается MySQL — то он это выражение 1=1 попросту отбросит, потому что оно всегда true.

Поскольку заранее не всегда ясно будет ли этот запрос динамическим или не будет — я приучил себя писать 1=1 всегда.
phpMyAdmin ставит 1
WHERE 1 AND…
Пользуюсь форматированием, похожим на вариант №2.
даже не знаю, по джойнам предпочитаю первый вариант, с ним проще охватить список задействованных таблиц, а в WHERE предпочитаю второй…
Второй лучше: в начале строки видно, что делается. Читается как на родном.
Мне кажется что лучший вариант для INNER'ов №2, а для AND'ов №1
У Кена Хендерсона в какой-то из книг есть целый раздел посвященный его рекомендациям по написанию запросов.
В целом, я с ним согласен, и при оформлении кода в основном пользуюсь его рекомендациями.
Получается достаточно читабельно с точки зрения стороннего разработчика.
P.S. И кто-нибудь может подсказать: что случлось с «избранным»?
Почему я не могу добавить топик в избранное? Куда делась кнопка?
за второй с маленькой модификацией
SELECT field
    , field1
    , field2
...


Так проще строку удалять.
удалять/комментировать
НЛО прилетело и опубликовало эту надпись здесь
Мне лично нравится так:
   SELECT  polls.`uid`, polls.`valid_days`
     FROM  yr_polls as polls
LEFT JOIN  yr_polls_choice as choice
       ON  polls.uid = choice.poll_id
    WHERE  polls.uid = p_id

Или

    UPDATE yr_polls_choice as pc
       SET pc.`choice` = 'aaaa'
     WHERE pc.`uid` = 1;


Вам не тяжело это все выравнивать по правому краю?
Наверняка строчки копипастятся и юзается волшебная кнопочка insert, которая позволяет включить режим замены. Главное, один раз подобрать, где будет находиться пробел.
Ну, разве что так =)
Лично мой стиль:

SELECT
    field1, , ..., fieldN
    fieldN+1, ... fieldN+M
FROM table AS t1
LEFT JOIN table2 AS t2 ON t2.field = t1.field
LEFT JOIN table3 AS t3 ON t3.field = t1.field AND t3.field2 = t2.fieldX
WHERE t3.field = 'something' AND t1.field = 'nothing' AND
        t2.field = 'anything'
ORDER BY t1.id DESC
GROUP BY t2.field
LIMIT 0, 10
SELECT
    t.field,
    t.field1,
    ...
FROM table t
INNER JOIN table1 t1  ON t1.id=t.id
INNER JOIN table2 t2  ON t2.id=t1.id
WHERE t.value='foo' AND t1.value='bar'
GROUP BY t.field
ORDER BY t.field
не используте длинные запросы =)
лучше пара коротких. база шустрее работать будет =)
лучше вообще без базы, так совсем быстро :P
заебали своими минусами =)
Мой вариант:
SELECT
	t1.row1,
	t1.row2,
	t1.row3
FROM table1 AS t1
INNER JOIN table2 AS t2 ON t2.row1 = t1.row1
INNER JOIN table3 AS t3 ON
	t3.row1 = t2.row1 AND
	t3.row2 = t2.row2
WHERE
	t1.row1 = x AND
	t1.row2 = y
ORDER BY t1.row3

тоесть все повторящиеся элементы переносятся на новую строку с отступом, если элемент один — он оставляется на той-же строке, ну и запятые, AND'ы и т.п. оставляются на предыдущей строке, чтобы все повторяющиеся элементы были на одном уровне.
НЛО прилетело и опубликовало эту надпись здесь
Использую ООПодход к форматированию :)

             $query = $db->select()
                         ->from('apartaments')
                         ->join(
                                 'apartaments_types',
                                 'apartaments.atype = apartaments_types.atype',
                                 array(
                                     'atype_name'
                                 )
                             )
                         ->join(
                                 'apartaments_pricetype', 
                                 'apartaments.pricetype = apartaments_pricetype.id', 
                                 array(
                                     'pricetype_text' => 'apartaments_pricetype.description'
                                 )
                            )
                         ->where('uid = ?', $id)
                         ->where('df = ?', 0)
                         ;
Имхо второй удобнее.
Не читал комментариев выше, так что могу повторить чьи-то мысли. Я предпочитаю 2-й вариант, причём не только для форматирования SQL, но и для форматирования программного кода.

Основная идея заключается в том, чтобы при чтении отслеживать, что происходит по первым символам строки.
Вот пример:

// Вариант 1
result = long_long_long_expression1 +
  long_long_long_expression2 *
  long_long_long_expression3;

// Вариант 2
result = long_long_long_expression1
  + long_long_long_expression2
  * long_long_long_expression3;


В первом случае глаз вынужден именно читать код, то есть бежать в конец строки и там смотреть. Во втором — глаз бежит просто сверху вниз по левому краю кода.

Ну и для особенных любителей красоты, можно использовать такую модификацию:

// Вариант 2.1
result = long_long_long_expression1
       + long_long_long_expression2
       * long_long_long_expression3;


:)
Кстати, у меня вопрос. Разве необходимо постоянно прописывать JOIN-ы? Т.е. я понимаю когда хочется явно указать порядок поиска при множественных связях, но большенство запросов элементарные и внутренние механизмы современный DBMS легко справляются с распознаванием джойнов. Так ли это?
Ну, джоины бывают разные
SQL-стандарт он как бы с 1992 года сильно расширился :-) Ну а многие кроме всего прочего свои расширения пихают. Почитайте что в Оракле используется для указаний разных видов соединений в where.

К примеру — where table1.id = table2.id (+)
> К примеру — where table1.id = table2.id (+)
Это костыль старых версий, которые не позволяет сделать сделать более одного левого соединения. 9-ка уже поддерживает джойны по человечески.

P.S.
Если вы считаете (+) удобным — значит вы с этим работали мало или совсем не работали.
Явное описание джоинов облегчит понимание запроса. Кроме того, условие соединение таблиц с джоинами записывается посе ON, а фильтрация выборки после WHERE. Cогласитесь, это лучше, чем мешать все в одну кашу после WHERE.
>>Cогласитесь, это лучше, чем мешать все в одну кашу после WHERE.

Кстати не соглашусь. Настоящая каша получается когда указаны все джойны, запрос читается куда хуже. Элементарной писанины куда больше. в Оракле даже специальные вещи придуманы типа (+) чтобы описывать типы разных соединений в where.

На sql.ru многие так и делают. К тому же видел несколько систем где отстутсвтие JOIN-ов в коде было частью их «code style convention». Сперва указываешь соедининия, потом уже бизнесс правила. Все просто, без какой-либо каши :-)
Мое мнение, «каша» — это когда в WHERE перемешаны условия соединения с условиями выборки.
Т.е. я понимаю когда хочется явно указать порядок поиска при множественных связях, но

Порядок соединения не задается порядком джойнов
А чем?
Зависит от СУБД. В оракл, например, специальными комментариями (хинтами). В MySQL есть ключевое слово STRAIGHT_JOIN. А в общем случае, когда порядок явно не задан, он определяется оптимизатором.
Точно, именно так.
Я делаю это так:

#Gets Nike's products
SELECT
	DISTINCT types.*
FROM
	(
		SELECT
			products.id,
			products.name,
			products.item,
			products.brand,
			products.sex,
			products.season
		FROM
			products
		INNER JOIN
			display
			ON
			display.item = products.season
			AND
			MID(
				IF(
					LENGTH(display.status) < 3,
					CONCAT(
						REPEAT(
							0,
							3 - LENGTH(display.status)
						),
						display.status
					),
					display.status
				),
				1,
				1
			) = 1
		INNER JOIN
			types
			ON
			types.brand = products.brand
			AND
			types.sex = products.sex
			AND
			types.season = products.season
		WHERE
			display.page = 289
		LIMIT	100
	) AS activeProducts
INNER JOIN
	types
	ON
	types.id = activeProducts.sex
WHERE
	types.brand = 'nike'
НЛО прилетело и опубликовало эту надпись здесь
Привет. А чего ужасного-то? А что с БД сервером такого станется от такого запроса или от какого-либо стиля форматирования?
ужасно не форматирование а код с функциями :(
а почему — гм… думаю правильно будет порекомендовать прочесть «Art of SQL». Легко находится на flazx.com
Я читал эту книгу и многие другие тоже, не стоит сразу так категоричто всех посылать пусть даже и в книжные магазины.

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

Поэтому я не вижу причин сразу плеваться на запрос увидев ф-ии в нем.
Спасибо за совет, по=читаю. Я выбрал этот запрос как пример, покрывающий наибольшее число конструкций.
И, если честно, оригинал этого запроса cодержит целых 3 (три) уровня derived. Да, я знаю, что это страшно. Если интересно, могу постараться донести почему.
НЛО прилетело и опубликовало эту надпись здесь
в моих проектах встречались запросы и побольше, гораздо больше :-)
хотя я не хотел меряться длинной :-))
НЛО прилетело и опубликовало эту надпись здесь
только так!

SELECT t.field, t.field1,…
    FROM table t INNER JOIN table1 t1 ON t1.id = t.id INNER JOIN table2 t2 ON t2.id=t1.id
    WHERE t.value = 'foo' AND t1.value = 'bar' GROUP BY t.field ORDER BY t.field

поля, from, where — сколько в строку влезет, остальное отступом
если все влазит в одну строку экрана то в одну строку.

а все остальные стили — ненужное изъебство с претензией на эстетство.
Соедините в своем стиле десяток таблиц + парочку derived tables и покажите коллеге, чтобы он разобрался что делает такой запрос…
думаю, лучше сразу пристрелить коллегу, чтобы не мучился :)

select
t
from Tools t
join t.parents t1
join t.childs t2
where
t.value='foo' and
t1.value='bar'
group by
t.field
order by
t.field
Упс, это не SQL, а HQL ^_^"""

На SQL уже не пишу ;)
Пардон за убитые отступы:
select
     t
from Tools t
     join t.parents t1
     join t.childs t2
where
     t.value='foo' and
     t1.value='bar'
group by
     t.field
order by
     t.field
Черт. Никак не отправлю то, что хотелось :(

from
     Tools t
мои пять копеек

SELECT t1.a, t1.b, t3,t, t3.s
       t2.c, t2.d, t3.h
  FROM db.table1 AS t1 
 INNER JOIN db.table2 AS t2 ON t1.g=t2.j
 INNER JOIN db.table3 AS t2 ON t3.g=t2.l
 WHERE t1.u > 10 
   AND t2.u > 10
   AND t3 < 10
 GROUP BY t2.a ASC
 ORDER BY t1.a DESC
 LIMIT 10

с вложенными вопросами намного сложнее.

кстати, я обратил внимание, что явно не указывается база данных… а ведь очень сильно помогает, когда проект работает с несколькими базами и еще хуже, с несколькими серверами. а при анализе slowquery.log то как помогает…

всегда пишу так: все ключевые слова отдельно и прописными — так легко понять, что за запрос. каждая новая строчка отдельно, чтобы можно было легко закомментировать без переноса запятых и ключевых слов (обычно для этого есть быстрая клавиша, которая срабатывает на той же строчке). имена всегда обособляю, чтобы проще искать при рефакторинге.

SELECT
	`t`.`field`
,	`t`.`field1` `another_field`

FROM
	`table` `t`
	INNER JOIN `table1` `t1` ON (`t1`.`id` = `t`.`id`)
	LEFT JOIN `table2` `t2` ON (`t2`.`id` = `t1`.`id`)
WHERE
	`t`.`value` = 'foo'
	AND `t1`.`value` = 'bar'
GROUP BY
	`t`.`field`
ORDER BY
	`t`.`field` DESC
чо то типа этого :)

SELECT
`t`.`field`,
`t`.`field1` `another_field`

FROM
`table` `t`
INNER JOIN
`table1` `t1`
ON
(`t1`.`id` = `t`.`id`)
LEFT JOIN
`table2` `t2`
ON
(`t2`.`id` = `t1`.`id`)
WHERE
`t`.`value` = 'foo' AND
`t1`.`value` = 'bar'
GROUP BY
`t`.`field`
ORDER BY
`t`.`field` DESC

блин как тут всталять отступы…
но думаю и так поянтно будет :)
Непонятно =)
второй вариант, только ON не переношу на новую строку
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории