Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Помогите с запросом

345
06 января 2011 года
vadim_k
312 / / 01.08.2006
Привет всем !

У нас уже 12 ночи но не могу успокоиться пока не получится
есть таблица(пример)

Код:
my-----you
 
  13-------1
  13-------1
  13-------1
  4-------1
  4-------1
  1-------13
  1-------13
  13-------2
  13-------2
  13-------2



Делаю запрос
 
Код:
select * from tab where  my= 13 OR you=13  GROUP BY my


выдаёт 3 строки(группы)
то есть строки таблицы 1-3 и 6-7 помещает в разные группы

а мне нужно чтобы все строки в которых число 13 встречается в любом столбце были в одной группе

тоесть чтобы запрос выдал 2 строки(группы)

думаю понятно объяснил
туплю что то

заранее спасибо
надеюсь поможите..
6
06 января 2011 года
George
4.1K / / 05.01.2007
Что значит в одной группе? Как, по-вашему, должен выглядеть результат?
8
07 января 2011 года
mfender
3.5K / / 15.06.2005
При чём тут группы? Данный запрос и выдаст два ряда результатов в одной всего-лишь группе my, соответственно критериям, где либо my=13, либо you=13. Результаты будут сгруппированны в два ряда, это видно невооружённым взглядом. Если будешь группировать по двум полям - будет три ряда результатов.

Чтобы было понятнее, напиши такой запрос:
 
Код:
SELECT table1.my,
       table1.you
FROM table1
GROUP BY table1.my
HAVING table1.my = 13 OR table1.you = 13

Группировка фактически даёт то, что ты по одному полю можешь указать DISTINCT, только тут получается по DISTINCT по двум критериям.
345
07 января 2011 года
vadim_k
312 / / 01.08.2006
извините может неправильно объяснил или
таблицу не точно нарисовал
у меня выдаёт 3строки

а если табл вот так вглядит
 
Код:
13-------1
  13-------1
  13-------1
  4-------1
  4-------1
  1-------13
  1-------13
  2-------13
  2-------13
  2-------13



тоесть группирует строки
так

1-3
6-7
8-10

а мне надо чтобы строки

1-3 и 6-7 попадали в одну строку результата

мне бы хотелось чтобы результат 2 строки был для обоих вариантов таблицы

задачка не так проста как кажется
8
07 января 2011 года
mfender
3.5K / / 15.06.2005
такого не бывает, это мистика. не может попасть в один ряд результат, где my=13 AND my=1.
345
07 января 2011 года
vadim_k
312 / / 01.08.2006
может я не толково объясняю
мне нужно сгруппировать строки уникальные
только по значению
а не по расположению

не важно
1----13
или
13----1

эти строки должны быть в одной группе
8
07 января 2011 года
mfender
3.5K / / 15.06.2005
чота ты сам запутался и всех путаешь. не могут быть в группе два разных значения группирующего поля. Всё что мне на ум приходит, тебе нужно добавить в ряд ещё два поля, как бы собирающие результат для второго критерия.
 
Код:
SELECT t1.my, t1.you, t2.my, t2.you
FROM table1 t1
INNER JOIN table1 t2 ON t1.my = t2.you
GROUP BY t1.my


UPD. Даже вот так:
 
Код:
SELECT t1.my, t1.you, t2.my, t2.you
FROM table1 t1
INNER JOIN table1 t2 ON t1.my = t2.you
WHERE t1.my=13
GROUP BY t1.my
345
07 января 2011 года
vadim_k
312 / / 01.08.2006
Наверное правда запутал
может тут не группировать нужно
а что то другое главное
что бы


1----13
и
13----1

были в одной строке результата
8
07 января 2011 года
mfender
3.5K / / 15.06.2005
ну вон чуть выше всё в одном ряду
345
07 января 2011 года
vadim_k
312 / / 01.08.2006
Прости немного не понял
нужно таблицу t2 создать
с такими же полями
8
07 января 2011 года
mfender
3.5K / / 15.06.2005
нет, t1 и t2 - это алиасы для одной и той же таблицы table1. Ну ты попробуй этот запрос - сразу всё поймёшь.
345
07 января 2011 года
vadim_k
312 / / 01.08.2006
сделал запрос по твоему второму варианту

вернул одну строку
6
07 января 2011 года
George
4.1K / / 05.01.2007
Извращенцы. Автору я бы порекомендовал объяснить задачу на более высоком уровне, что за данные он хочет получить, потому что на низком уровне получается какая-то ахинея и извращения.
345
07 января 2011 года
vadim_k
312 / / 01.08.2006
постараюсь подробно не на примерах а на реальной таблице
есть таблица переписки
столбцы
nu - индекс автоинкремент
n_pa - номер автора сообщения
n_to - номер адресата
tx - текст сообщения
new_s - прочитано или нет(0 или 1)
data - дата сообщения

nu-----n_pa-----n_to-----tx-----data


например пользователь с номером 13 написал сообщение пользователю 1
получаем

n_pa-----n_to
13--------1

в ответ пользователь 1 написал ответ пользователю 13

n_pa-----n_to
1--------13

ну и так далее

потом наверное многие видели делаю как переписка в однокласниках

из таблицы нужно выбрать уникальные диалоги

тоесть все записи

n_pa-----n_to
13--------1
.....
1--------13
это один диалог

а например

n_pa-----n_to
13--------5
.....
5--------13

другой и так далее нужно чтобы результат возвращал все уникальные диалоги причём поля new_s могут иметь разные значения 0 или 1

не знаю как понятней
8
07 января 2011 года
mfender
3.5K / / 15.06.2005
не парся с запросом. он тебе никогда не вернёт того что ты хочешь. или пиши процедуру, где будешь обходить все диалоги по очереди.
правда, есть ещё вариант. насколько я понял, тебя последовательность мессаг в переписке определяется только временем? (кстати, date - зарезервированное слово и поле нельзя так называть) Если бы у тебя у мессаги был идентификатор её предка, то можно было бы все "узлы" рекурсивно пробежать. У тебя всё в одну колонку. Значит нужно выбрать во вложенном запросе идентификаторы рядов, отсортировав их по времени и авторам, и тогда тебе вернутся сообщения с этими идентификаторами, отсортированные как надо.
8
07 января 2011 года
mfender
3.5K / / 15.06.2005
SELECT *
FROM
table1
WHERE
id IN (SELECT id FROM table1 WHERE my=13 OR you=13 ORDER BY date ASC)

И не надо никаких группировок. И всё это в цикл завернуть, если хостёр позволяет stored procedures )))))
345
07 января 2011 года
vadim_k
312 / / 01.08.2006
я опсался у меня не date а data

но не суть сортировать хотел не по дате а по количеству новых
new_s=1 значит непрочитанное

остальные сотртировать по id(nu)

сердцем чую запрос написать можно

а может сначала выбрать
(SELECT id FROM table1 WHERE my=13 ORDER BY nu desc)
(SELECT id FROM table1 WHERE you=13 ORDER BY nu desc)
а потом их как то объдинить
8
07 января 2011 года
mfender
3.5K / / 15.06.2005
Вобщем, введи ещё одно поле answer_by, в который будешь писать идентификатор сообщения, на которое ответ случился. Соответственно, у самого первого сообщения будет answer_by=0. Вот тебе и первые сообщения в переписках. А дальше циклами, циклами по всей ёлке.
8
07 января 2011 года
mfender
3.5K / / 15.06.2005
Цитата: vadim_k
а может сначала выбрать
(SELECT id FROM table1 WHERE my=13 ORDER BY nu desc)
(SELECT id FROM table1 WHERE you=13 ORDER BY nu desc)
а потом их как то объдинить



Эти два запроса можно объединить, вставив между ними UNION. и скобки убрать.

UPD. и сортируй не по id, а по времени. Идентификатор с автоинкрементом может подвести.

385
07 января 2011 года
SomewherSomehow
477 / / 25.07.2004
vadim_k,
Какая субд у вас?
[quote=mfender]
не парся с запросом. он тебе никогда не вернёт того что ты хочешь.
[/quote]
Вообще-то можно и одним запросом.
А циклы - это плохо. Где есть возможность - надо стараться обходиться без них.
345
07 января 2011 года
vadim_k
312 / / 01.08.2006
У меня стандарт
MySql 5.0, PHP

Я тоже чувствую одним можно
рою книги
385
07 января 2011 года
SomewherSomehow
477 / / 25.07.2004
Попробуйте порыть в направлении подзапрос+case+оконные функции (можо и без них, но громоздко получится, хотя по-моему мускуль позволяет указывать в селекте поля не включенные в группировку, так что можно попробовать и группировкой обойтись).

А идея такая. В подзапросе значения полей меняете местами (при помощи case), если одно больше другого, при этом, если значения поменялись устанавливаете признак что они были поменяны, потом запросом из подзапроса выбираете только уникальные (при помощи оконной функции или группировки). Потом в том же запросе смотрите на прзнак, если значения полей менялись местами - меняете их обратно.

Могу привести пример такого решения, но только на mssql, если он вам поможет...
345
07 января 2011 года
vadim_k
312 / / 01.08.2006
конечно лучше на пример посмотреть а то я не особо силён в Sql
345
07 января 2011 года
vadim_k
312 / / 01.08.2006
Вот предложили люди

 
Код:
(SELECT DISTINCT n_pa as first, n_to as second from tab
WHERE my=13)
UNION
(SELECT DISTINCT n_to as first, n_pa as second from tab
WHERE you=13)


попробовал количество строк вроде правильно выдаёт
осталось только доработать что бы количество сообщений
подсчитывать
раньше делал так

COUNT(if(n_to = 13 and new_s = 0,1,NULL)) AS mi_mess_new
куда теперь это пристроить
345
08 января 2011 года
vadim_k
312 / / 01.08.2006
Спасибо за помощь проблему решил всё просто оказалось может кому то поможет


SELECT t1.*,
if(t1.n_pa > t1.n_to,t1.n_pa,t1.n_to) AS first,
if(t1.n_pa > t1.n_to,t1.n_to,t1.n_pa) AS second,

FROM messeges AS t1

where t1.n_to=13 OR t1.n_pa=13 GROUP BY first,second
385
09 января 2011 года
SomewherSomehow
477 / / 25.07.2004
вот я примерно про то же самое и говорил, переставить местами поля.
только единственный минус, у вас в запросе. Если допустим была только одна запись у которой t1.n_pa < t1.n_to, то вы поменяв там поля местами получите ту запись которой фактически не было в исходных данных.

Т.е. например было 1, 3 и 3, 1. Вы поменяли стало 3,1 и 3, 1 берете одну из них. Тут все ок. А если была только одна запись например 1, 6. То в итоговой выборке у вас будет запись 6, 1 - а такой записи фактически не существует.

По этому я предложил решить эту проблему через подзапрос. Т.е. ввести признак в подзапросе и если смена фактически была - то меняем обратно во внешенм запросе.
Хотя если для вашей задачи это не важно, то можно и не париться.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог