Значения в полях Num_One, Num_Two, Num_Three вычислены и могут совпадать для различных записей.
Помогите составить SELECT так, чтобы найти эти совпадения.
Например по полю Num_One нужно получить следующие записи
SELECT mytable.id, mytable.name, mytable.num_one (и т.д.)
FROM mytable
GROUP BY mytable.num_one, mytable.id, mytable.name
А вот если тебе нужно получить только строки с определенным значением поля num_one, например все с num_one=1.003424 то маленько поинтересноей:
SELECT mytable.id, mytable.name, mytable.num_one
FROM mytable LEFT JOIN mytable AS table2 ON table2.id=mytable.id
GROUP BY mytable.num_one, mytable.id, mytable.name
HAVING mytable.num_one=1.003424
Суть в том что мы объединяем таблицу саму с собой. Запросы проверены в Access, в других СУБД они могут незначительно отличаться синтаксисом, но идея будет одна и та же.
Здравствуйте Xenia, Вы писали:
X>Делается это очень просто:
Что "ЭТО"? Об "этом" в этом форуме не говорят. А ни на один вопрос Вы не ответили.
X>
X>SELECT mytable.id, mytable.name, mytable.num_one (и т.д.)
X>FROM mytable
X>GROUP BY mytable.num_one, mytable.id, mytable.name
X>
Результатом данного селекта будет список _всех_ записей таблицы, сгруппированных по значению поля num_one и дальше по списку.
Вопрос: Какому из поставленных вопросов удовлетворяет этот ответ?
Ответ: Никакому. Следовательно, очень полезен.
X>А вот если тебе нужно получить только строки с определенным значением поля num_one, например все с num_one=1.003424 то маленько поинтересноей: X>
X>SELECT mytable.id, mytable.name, mytable.num_one
X>FROM mytable LEFT JOIN mytable AS table2 ON table2.id=mytable.id
X>GROUP BY mytable.num_one, mytable.id, mytable.name
X>HAVING mytable.num_one=1.003424
X>
Превосходно. А почему не where num_one=значение? Результат в смысле выданных записей одинаков, а вот производительность — в такой области желудка, что хуже не предумаешь. Ведь Вы наверняка знаете, что в MySQL (как и в многих других) раздел HAVING опрератора SELECT выполняется НЕПОСРЕДСТВЕННО ПЕРЕД ОТПРАВКОЙ ДАННЫХ КЛИЕНТУ, т.е. о оптимизации такого запроса не может быть и речи, и все, что могло бы быть отсеяно заранее с помощью WHERE, будет тянуться до самого последнего момента.
Второе: если известен литерал значения, по которому записи надо получить, то зачем вообще это все? При известном значении, по которому нужно получить набор записей, можно опять таки сделать все с помощью where и без объединения. Это — тоже не ответ на вопрос.
Самым для Вас приятным наверное будет тот факт, что выше приведенный оператор даст пустое множество записей. Ну, не сравнивается как-то литерал с точным значением поля типа FLOAT, даже с тем, которое мы туда положили.
X>Суть в том что мы объединяем таблицу саму с собой. Запросы проверены в Access, в других СУБД они могут незначительно отличаться синтаксисом, но идея будет одна и та же.
Все дело в том, что MySQL — не Access, и не другая база данных. Она совсем другая.
2 Orion9:
В ситуации, когда нет views и подзапросов, такая ситуация может быть обойдена с помощью скрипта (набора опреаторов) с привлечением временных таблиц.
Описание таблицы:
DROP TABLE/*!32200 IF EXISTS*/ t1;
CREATE TABLE/*!32300 IF NOT EXISTS*/ t1 (
id int(3) NOT NULL DEFAULT '0' ,
name varchar(255) ,
f1 float DEFAULT '0' ,
f2 float DEFAULT '0' ,
f3 float DEFAULT '0'
);
INSERT INTO t1 VALUES("1","name1","0.0123769","1.38476","0.39847");
INSERT INTO t1 VALUES("2","name2","1.00342","1.54435","0.3547");
INSERT INTO t1 VALUES("3","name3","0.983476","3.12341","4.39848");
INSERT INTO t1 VALUES("4","name4","2.34532","2.39486","5.23234");
INSERT INTO t1 VALUES("5","name5","8.23099","3.12341","5.23234");
INSERT INTO t1 VALUES("6","name6","0.342231","1.54435","3.9845");
INSERT INTO t1 VALUES("7","name7","8.23099","3.12341","0.354234");
INSERT INTO t1 VALUES("8","name8","1.00342","1.58935","0.469898");
Получение значений поля f1, группа записей по которому содержит хотя-бы 2 записи:
select f1 from t1 group by f1 having count(*) > 1;
Это дело (результат) можно сохранить во временной таблице, и селектом по 2-м таблицам получить то, что ты хотел в первом вопросе. Врем. таблицы — убить.
Согласна, стормозила. Kaa>В ситуации, когда нет views и подзапросов, такая ситуация может быть обойдена с помощью скрипта (набора опреаторов) с привлечением временных таблиц. Kaa>Получение значений поля f1, группа записей по которому содержит хотя-бы 2 записи: Kaa>
select f1 from t1 group by f1 having count(*) > 1;
Kaa>Это дело (результат) можно сохранить во временной таблице, и селектом по 2-м таблицам получить то, что ты хотел в первом вопросе. Врем. таблицы — убить. Kaa>По-другому пока не получилось. Но вот с этим не соглашусь. Если совсем другая СУБД MySql поддерживает вложенные запросы — то можно обойтись и без временных таблиц:
SELECT id, num_one
FROM mytable
WHERE num_one in(
SELECT num_one
FROM mytable
GROUP BY num_one
having count(*)>1
)
Если не поддерживает — тогда временные таблицы.
Что касается оптимизации, то без HAVING все равно не обойтись, и в Вашем ответе он так же присутствует.
Согласна, стормозила. Kaa>В ситуации, когда нет views и подзапросов, такая ситуация может быть обойдена с помощью скрипта (набора опреаторов) с привлечением временных таблиц. Kaa>Получение значений поля f1, группа записей по которому содержит хотя-бы 2 записи: Kaa>
select f1 from t1 group by f1 having count(*) > 1;
Kaa>Это дело (результат) можно сохранить во временной таблице, и селектом по 2-м таблицам получить то, что ты хотел в первом вопросе. Врем. таблицы — убить. Kaa>По-другому пока не получилось. Но вот с этим не соглашусь. Если совсем другая СУБД MySql поддерживает вложенные запросы — то можно обойтись и без временных таблиц:
SELECT id, num_one
FROM mytable
WHERE num_one in(
SELECT num_one
FROM mytable
GROUP BY num_one
having count(*)>1
)
Если не поддерживает — тогда временные таблицы.
Что касается оптимизации, то без HAVING все равно не обойтись, и в Вашем ответе он так же присутствует.
O>Значения в полях Num_One, Num_Two, Num_Three вычислены и могут совпадать для различных записей. O>Помогите составить SELECT так, чтобы найти эти совпадения.
Все что, напишу ниже проверялось для MS SQL Server 2000, но в запросах не используется ничего специфичного T-SQL, поэтому наверно должно все работать. В крайнем случае можно переписать через временные таблицы.
В таблице t твои данные, но т.к. точность при хранении float теряется, они выглядят так:
declare @e float
set @e = 0.01
select t.*
from t inner join ( select t.[id]
from t inner join ( select num_three
from t ) as tt on tt.num_three >= t.num_three - @e and tt.num_three <= t.num_three + @e
group by t.[id]
having count(*) > 1 ) as ttt on ttt.[id] = t.[id]
Результат для точности 0.01 отличается от твоего, так как одинаковые числа тоже удовлтворяют условиям точности, а num_three в первой строке 0.39847, а не 0.359847:
Здравствуйте Xenia, Вы писали:
X>Что касается оптимизации, то без HAVING все равно не обойтись, и в Вашем ответе он так же присутствует.
Я не знаком с MySQL, но в SQL Server'е без HAVING можно обойтись с полпинка (вариант для поля #1):
select id,name,num_one,num_two,num_three from table where exists (select null from table t2 where t2.id<>id and t2.num_one=num_one)
Здравствуйте Xenia, Вы писали:
X>Согласна, стормозила. Kaa>>В ситуации, когда нет views и подзапросов, такая ситуация может быть обойдена с помощью скрипта (набора опреаторов) с привлечением временных таблиц. X>Если совсем другая СУБД MySql поддерживает вложенные запросы ...
Не поддерживает. Об том и речь.
X>Что касается оптимизации, то без HAVING все равно не обойтись, и в Вашем ответе он так же присутствует.
В моем он присутствует там, где и должен, т.е. когда весь результат запроса вычислен, и осталось из него выкинуть те группы, которые условию HAVING не удовлетворяют. Заметь, на уже готовом результате. И условие — количество записей в группе. Это — никак в WHERE не запихнуть.
В твоем случае же все данные таблицы группируются, а уже затем по HAVING выкидываются записи, которые до сего места вообще доходить не должны, т.к. условие, приведенное в твоем запросе, относится не к каждой отдельно взятой группе записей, а к каждой записи в отдельности.
Здравствуйте Lexey, Вы писали:
L>Здравствуйте Xenia, Вы писали:
X>>Что касается оптимизации, то без HAVING все равно не обойтись, и в Вашем ответе он так же присутствует.
L>Я не знаком с MySQL, но в SQL Server'е без HAVING можно обойтись с полпинка (вариант для поля #1): L>select id,name,num_one,num_two,num_three from table where exists (select null from table t2 where t2.id<>id and t2.num_one=num_one)
Запрос должен быть чуть другим:
select id, name, num_one, num_two, num_three
from t
where exists( select null from t as t2 where t2.id <> t.id and t2.num_one = t.num_one)
Здравствуйте beginner, Вы писали:
L>>Я не знаком с MySQL, но в SQL Server'е без HAVING можно обойтись с полпинка (вариант для поля #1): L>>select id,name,num_one,num_two,num_three from table where exists (select null from table t2 where t2.id<>id and t2.num_one=num_one)
B>Запрос должен быть чуть другим: B>
B>select id, name, num_one, num_two, num_three
B>from t
B>where exists( select null from t as t2 where t2.id <> t.id and t2.num_one = t.num_one)
B>
А какая разница? Тут и без алиаса на первую таблицу не должно быть конфликта имен. Впрочем, проверять сейчас мне влом.
Здравствуйте Lexey, Вы писали:
L>А какая разница? Тут и без алиаса на первую таблицу не должно быть конфликта имен. Впрочем, проверять сейчас мне влом.
Да нет, разница есть. (мне проверять было не влом )
Здравствуйте Lexey, Вы писали:
L>А какая разница? Тут и без алиаса на первую таблицу не должно быть конфликта имен. Впрочем, проверять сейчас мне влом.
В дополнение, вот что написано в BOL
The general rule is that column names in a statement are implicitly qualified by
the table referenced in the FROM clause at the same level.
BOL — Accessing and Changing Relational Data — Advanced Query Concepts — Subquery Fundamentals — Qualifying Column Names in Subqueries
Здравствуйте Kost, Вы писали:
K>Ребята,
K>а чем вариант:
K>select t1.id, t1.name, t1.num_one, t1.num_two, t1.num_three K>from mytable t1, mytable t2 K>where t2.id <> t1.id and t2.num_one = t.num_one
K>хуже, чем вы предлагаете:
K>select id, name, num_one, num_two, num_three K>from t K>where exists( select null from t as t2 where t2.id <> t.id and t2.num_one = t.num_one)
K>Или они одинаковые
Одинаковые. Физическая операция и в первом и во втором запросе — nested loops. Отличаются только логические операции: в первом — inner join, у втором — left semi join.