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

192
15 августа 2018, 22:20

SqlFiddle

Мне непонятно, почему в указанном запросе из вьюхи возвращается только одна запись?
При том, что тот же код этой вьюхи с тем же условием возвращает уже две записи.

Сильно подозреваю, что это как-то связано с порядком group by и where при использовании вьюхи. У меня уже были какие-то похожие проблемы тут и тут.

Структура:

  • articles(id, name)
  • authors(id, name)
  • jobs(id, name)
  • authors_connection(article_id, author_id, job_id)

ссылки соответственно article_id на таблицу article стобец id, author_id на authors.id, job_id на jobs.id.

У одной статьи может быть несколько авторов. У одного автора может быть несколько мест работы, но на выходе вьюхи должно остаться только одно любое. Вьюха объединяет эти разрозненные таблицы в одну таблицу авторов с одним указанным местом работы.

Answer 1

Mysql нарушает стандарт в плане нестрогой группировки.
В последних версиях она ещё и отключена по умолчанию.

Добавьте все используемые поля в GROUP BY (либо уберите GROUP BY вообще) и получите идентичный результат (2 записи) при запросе из View

create view v_authors as
select author_id as id, c.article_id, p.name, j.name as job_name
from authors_connection c
inner join articles a on a.id = c.article_id
inner join authors p on p.id = c.author_id
left join jobs j on j.id = c.job_id
group by c.author_id, c.article_id, p.name, j.name; -- Тут

С другой стороны, очевидно, что запрос без view работает только потому, что фильтр применяется до группировки.

Запрос:

select * from(
  select author_id as id, c.article_id, p.name, j.name as job_name
  from authors_connection c
  inner join articles a on a.id = c.article_id
  inner join authors p on p.id = c.author_id
  left join jobs j on j.id = c.job_id
  group by c.author_id
) t where article_id = 3

также вернёт одну запись (скорее всего, это похоже на UB).
Таким образом, придётся вынести группировку из view.
Или, в процессе группировки Вы потеряете данные, по которым собираетесь фильтровать.

Answer 2

Вам следует ознакомится с ответом @Mike относительно использования group by

Что происходит в ваших запросах.

Если вы выполните запрос без where и group by:

select author_id as id, c.article_id, p.name, j.name as job_name
from authors_connection c
inner join articles a on a.id = c.article_id
inner join authors p on p.id = c.author_id
left join jobs j on j.id = c.job_id;

то получите набор из 4 строк: 3 статьи первого автора и статья #3 второго.

Далее при работе со вьюшкой вы проводите группировку по автору. В результате чего у вас остается 2 строки. Второй автор там как был с третьей статьей так и остался, а вот группировка первого автор дает вам неопределенный результат. У вас было три строки этого автора, а после группировки остается одна. Какая из них именно остается - не определено, т.к. группировка в целом выполнена неправильно. Осталась первая попавшаяся, и это вероятно строка с arcticle_id = 1. Поэтому после фильтрации вьюшки по article_id = 3 осталась единственная строка второго автора. При удачном расположении звезд этот запрос может вернуть и 2 строки, если после группировки останется не произвольная первая строка первого автора, а третья. Индекс там по убыванию будет, или еще чего.

Во втором же случае из полных четырех строк вы сначала фильтруете статьи с id = 3, остается две строки разных авторов. И теперь при группировке остается все те же две разных строки.

Answer 3

В mysql почти нет параметризованных отображений.

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

create function param1() returns INTEGER NO SQL return @param1;
create view v_authors as
select author_id as id
  , c.article_id
  , min(p.name) name
  , min(j.name) as job_name
from authors_connection c
inner join articles a on a.id = c.article_id
inner join authors p on p.id = c.author_id
left join jobs j on j.id = c.job_id
where c.article_id = param1()
group by c.author_id, c.article_id;

Fiddle

READ ALSO
function - Смысл флага deterministic

function - Смысл флага deterministic

В чём разница между детерменированной и недетерминированной функцией? Я надеялся, что deterministic заставит СУБД посчитать функцию чистой и закеширует...

196
Как добавить кнопку в инпут? html

Как добавить кнопку в инпут? html

Всем привет, помогите, пожалуйстаКак в HTML добавить <input type="button"> в <input type="text">, чтобы получилось как на фото? Заранее спасибо

183
Css. Высота блока по вертикали!

Css. Высота блока по вертикали!

Есть 3 блока header, content, footer

179