помогите построить SELECT
От: orion9  
Дата: 21.04.02 06:07
Оценка:
Есть такая таблица mytable
id    Name    Num_One        Num_Two        Num_Three
1    name1    0.0123769    1.384756432    0.39847
2    name2    1.003424    1.544345    0.3546999445
3    name3    0.9834759234    3.1234123    4.3984798
4    name4    2.34532424    2.3948578023    5.232344
5    name5    8.230985423    3.1234123    5.232344
6    name6    0.3422309    1.544345    3.9845
7    nume7    8.230985423    3.1234123    0.354234
8    name8    1.003424    1.58934565    0.469897545

Значения в полях Num_One, Num_Two, Num_Three вычислены и могут совпадать для различных записей.
Помогите составить SELECT так, чтобы найти эти совпадения.

Например по полю Num_One нужно получить следующие записи
2    name2    1.003424    1.544345    0.3546999445
8    name8    1.003424    1.58934565    0.469897545

5    name5    8.230985423    3.1234123    5.232344
7    nume7    8.230985423    3.1234123    0.354234


По полю Num_Two записи
2    name2    1.003424    1.544345    0.3546999445
6    name6    0.3422309    1.544345    3.9845

3    name3    0.9834759234    3.1234123    4.3984798
5    name5    8.230985423    3.1234123    5.232344
7    nume7    8.230985423    3.1234123    0.354234


По полю Num_Three нужны записи
4    name4    2.34532424    2.3948578023    5.232344
5    name5    8.230985423    3.1234123    5.232344


И как сделать запрос с ограничением точности
Num_Three X.XX
1    name1    0.0123769    1.384756432    0.359847
2    name2    1.003424    1.544345    0.3546999445
7    nume7    8.230985423    3.1234123    0.354234

Num_Three X.XXX
2    name2    1.003424    1.544345    0.3546999445
7    nume7    8.230985423    3.1234123    0.354234


Можно вообще построить такие запросы или это программно придется делать.
(DB MySQL)
Re: помогите построить SELECT
От: Xenia США  
Дата: 21.04.02 07:48
Оценка:
Здравствуйте orion9, Вы писали:

O>Есть такая таблица mytable

O>
O>id    Name    Num_One        Num_Two        Num_Three
O>1    name1    0.0123769    1.384756432    0.39847
O>2    name2    1.003424    1.544345    0.3546999445
O>3    name3    0.9834759234    3.1234123    4.3984798
O>4    name4    2.34532424    2.3948578023    5.232344
O>5    name5    8.230985423    3.1234123    5.232344
O>6    name6    0.3422309    1.544345    3.9845
O>7    nume7    8.230985423    3.1234123    0.354234
O>8    name8    1.003424    1.58934565    0.469897545
O>

Делается это очень просто:

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, в других СУБД они могут незначительно отличаться синтаксисом, но идея будет одна и та же.
Re[2]: помогите построить SELECT
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 21.04.02 09:28
Оценка:
Здравствуйте 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-м таблицам получить то, что ты хотел в первом вопросе. Врем. таблицы — убить.

По-другому пока не получилось.

С уважением
Алексей Кирдин
Re[3]: помогите построить SELECT
От: Xenia США  
Дата: 21.04.02 11:16
Оценка:
Согласна, стормозила.
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 все равно не обойтись, и в Вашем ответе он так же присутствует.
Re[3]: помогите построить SELECT
От: Xenia США  
Дата: 21.04.02 11:16
Оценка:
Согласна, стормозила.
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 все равно не обойтись, и в Вашем ответе он так же присутствует.
Re: помогите построить SELECT
От: beginner Россия  
Дата: 21.04.02 11:24
Оценка: 3 (1)
Здравствуйте orion9, Вы писали:

O>Есть такая таблица mytable

O>
O>id    Name    Num_One        Num_Two        Num_Three
O>1    name1    0.0123769    1.384756432    0.39847
O>2    name2    1.003424    1.544345    0.3546999445
O>3    name3    0.9834759234    3.1234123    4.3984798
O>4    name4    2.34532424    2.3948578023    5.232344
O>5    name5    8.230985423    3.1234123    5.232344
O>6    name6    0.3422309    1.544345    3.9845
O>7    nume7    8.230985423    3.1234123    0.354234
O>8    name8    1.003424    1.58934565    0.469897545
O>

O>Значения в полях Num_One, Num_Two, Num_Three вычислены и могут совпадать для различных записей.
O>Помогите составить SELECT так, чтобы найти эти совпадения.

Все что, напишу ниже проверялось для MS SQL Server 2000, но в запросах не используется ничего специфичного T-SQL, поэтому наверно должно все работать. В крайнем случае можно переписать через временные таблицы.

В таблице t твои данные, но т.к. точность при хранении float теряется, они выглядят так:
id    name    num_one            num_two            num_three
1    name1    0.0123769        1.3847564320000001    0.39846999999999999
2    name2    1.0034240000000001    1.55345            0.35469994449999998
3    name3    0.98347592340000001    3.1234123        4.3984797999999996
4    name4    2.3453242400000001    2.3948578022999998    5.2323440000000003
5    name5    8.2309854229999999    3.1234123        5.2323440000000003
6    name6    0.3422309        1.55345            3.9845000000000002
7    name7    8.2309854229999999    3.1234123        0.35423399999999999
8    name8    1.0034240000000001    1.5893456500000001    0.46989754500000003


O>Например по полю Num_One нужно получить следующие записи

O>
O>2    name2    1.003424    1.544345    0.3546999445
O>8    name8    1.003424    1.58934565    0.469897545

O>5    name5    8.230985423    3.1234123    5.232344
O>7    nume7    8.230985423    3.1234123    0.354234
O>


select t.*
from t inner join ( select num_one
            from t
            group by num_one
            having count(*) > 1 ) as tt on tt.num_one = t.num_one


O>И как сделать запрос с ограничением точности

O>
O>Num_Three X.XX
O>1    name1    0.0123769    1.384756432    0.359847
O>2    name2    1.003424    1.544345    0.3546999445
O>7    nume7    8.230985423    3.1234123    0.354234

O>Num_Three X.XXX
O>2    name2    1.003424    1.544345    0.3546999445
O>7    nume7    8.230985423    3.1234123    0.354234
O>


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:
id    name    num_one            num_two            num_three
2    name2    1.0034240000000001    1.55345            0.35469994449999998
4    name4    2.3453242400000001    2.3948578022999998    5.2323440000000003
5    name5    8.2309854229999999    3.1234123        5.2323440000000003
7    name7    8.2309854229999999    3.1234123        0.35423399999999999
__________________
per aspera ad astra
Re[4]: помогите построить SELECT
От: Lexey Россия  
Дата: 21.04.02 12:17
Оценка: 1 (1)
Здравствуйте 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)
Re[4]: помогите построить SELECT
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 21.04.02 12:27
Оценка: 2 (1)
Здравствуйте Xenia, Вы писали:

X>Согласна, стормозила.

Kaa>>В ситуации, когда нет views и подзапросов, такая ситуация может быть обойдена с помощью скрипта (набора опреаторов) с привлечением временных таблиц.
X>Если совсем другая СУБД MySql поддерживает вложенные запросы ...

Не поддерживает. Об том и речь.

X>Что касается оптимизации, то без HAVING все равно не обойтись, и в Вашем ответе он так же присутствует.

В моем он присутствует там, где и должен, т.е. когда весь результат запроса вычислен, и осталось из него выкинуть те группы, которые условию HAVING не удовлетворяют. Заметь, на уже готовом результате. И условие — количество записей в группе. Это — никак в WHERE не запихнуть.

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

С уважением
Алексей Кирдин
Re[5]: помогите построить SELECT
От: beginner Россия  
Дата: 21.04.02 12:35
Оценка: 3 (1)
Здравствуйте 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)
__________________
per aspera ad astra
Re[6]: помогите построить SELECT
От: Lexey Россия  
Дата: 22.04.02 06:52
Оценка:
Здравствуйте 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>


А какая разница? Тут и без алиаса на первую таблицу не должно быть конфликта имен. Впрочем, проверять сейчас мне влом.
Re[7]: помогите построить SELECT
От: beginner Россия  
Дата: 22.04.02 14:25
Оценка:
Здравствуйте Lexey, Вы писали:

L>А какая разница? Тут и без алиаса на первую таблицу не должно быть конфликта имен. Впрочем, проверять сейчас мне влом.


Да нет, разница есть. (мне проверять было не влом )
__________________
per aspera ad astra
Re[7]: помогите построить SELECT
От: beginner Россия  
Дата: 22.04.02 15:36
Оценка:
Здравствуйте 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
__________________
per aspera ad astra
Re[8]: помогите построить SELECT
От: Lexey Россия  
Дата: 23.04.02 06:26
Оценка:
Здравствуйте beginner, Вы писали:

B>В дополнение, вот что написано в BOL


B>
B>The general rule is that column names in a statement are implicitly qualified by
B>the table referenced in the FROM clause at the same level.
B>


B>BOL — Accessing and Changing Relational Data — Advanced Query Concepts — Subquery Fundamentals — Qualifying Column Names in Subqueries


Убедил.
Re: помогите построить SELECT
От: orion9  
Дата: 24.04.02 00:55
Оценка:
Благодарю всех за проявленное внимание к вопросу!!!
Спасибо!
Re: помогите построить SELECT
От: Kost  
Дата: 24.04.02 10:56
Оценка:
Ребята,

а чем вариант:

select t1.id, t1.name, t1.num_one, t1.num_two, t1.num_three
from mytable t1, mytable t2
where t2.id <> t1.id and t2.num_one = t.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)

Или они одинаковые
Re[2]: помогите построить SELECT
От: beginner Россия  
Дата: 24.04.02 20:43
Оценка:
Здравствуйте 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.
__________________
per aspera ad astra
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.