Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Хитрая выборка из двух таблиц / 23 сообщений из 23, страница 1 из 1
01.04.2003, 15:56
    #32131075
BigHarry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Опять я вас достаю своими проблемами - но прошу извинить - больше обратится некуда, а я в TSQL хреново понимаю...
Есть две таблицы:

tovar - таблица характеристик товаров
================
Kod - уникальный код товара
Name - название товара
================

zena - таблица с историями цен товаров
================
Kod - код товара
Data - дата установки цены на товар
Price - значение цены на дату
================

Как можно сделать выборку, что бы в нее попали название товаров и цены этих товаров на определенную дату?
Типа такая должна быть картина:

+=========================+=======+
| Товар | Цена |
+=========================+=======+
Телевизор Sony E-25 7000
Чайник Скарлет-1022 800
Утюг PHILIPS-78 950
==================================
Можно-ли это сделать опять-таки одним запросом, без временных таблиц?
...
Рейтинг: 0 / 0
01.04.2003, 16:07
    #32131086
BigHarry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
CREATE DATABASE sex;
USE sex;

CREATE TABLE tovar (
  Kod CHAR( 4 ),
  Name VARCHAR( 50 )
);

CREATE TABLE Zena (
  Kod CHAR( 4 ),
  Data DATE,
  Price SMALLINT( 5 ) UNSIGNED
);

INSERT INTO tovar VALUES ('1077', 'Чайник Скарлет-1022');
INSERT INTO tovar VALUES ('5618', 'Утюг PHILIPS-78');
INSERT INTO tovar VALUES ('3388', 'Телевизор Sony E-25');

INSERT INTO Zena VALUES ('5618', '2002-12-30',  900 );
INSERT INTO Zena VALUES ('5618', '2003-01-25',  920 );
INSERT INTO Zena VALUES ('5618', '2003-03-02',  950 );

INSERT INTO Zena VALUES ('1077', '2002-12-30',  750 );
INSERT INTO Zena VALUES ('1077', '2003-02-18',  800 );

INSERT INTO Zena VALUES ('3388', '2002-12-30',  6580 );
INSERT INTO Zena VALUES ('3388', '2003-01-15',  7200 );
INSERT INTO Zena VALUES ('3388', '2003-03-02',  7000 );
...
Рейтинг: 0 / 0
01.04.2003, 16:34
    #32131136
Артем1
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
declare @d DATETIME
set @d = '20030125'

select t.*, 
      (select top  1  Price 
       from zena 
       where 
         (Kod = t.Kod) 
          and 
         (  DateDiff(day, Data, @d) = (select min( DateDiff(day, Data, @d) ) from zena where zena.kod = t.kod ) ) ) 
from tovar t


Как то так должно работать. По крайне мере результат сходится.
Писал на Transact-SQL (у меня SQL Server), так что адаптируеш сам.
Сорри за корявое оформление.
...
Рейтинг: 0 / 0
01.04.2003, 16:57
    #32131174
mahoune
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Он бы адаптировал. Только навряд ли у него есть вложенные запросы в MySQL!

2BigHarry, у делали-же с этой базой уже что-то тут?!
...
Рейтинг: 0 / 0
01.04.2003, 17:28
    #32131225
BigHarry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Да - это для МуСкуля...
Тама вложенных запросов (в трешке) точно нету.
Четверка - ещо сырая, что бы ее ставить...
(2) mahoune - да - делали, но там была другая проблема - и она не без вашей помощи разрешилась...
...
Рейтинг: 0 / 0
01.04.2003, 19:07
    #32131339
medved
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Короче говоря....
1. если тебе нужен запрос, который тебе выдает - у каких товаров были изменения по цене за данную дату, то никаких проблем:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
select
		tovar.Name,
		zena.Price,
		 "2002 - 12 - 31 " as Data
from 
		zena,
		tovar
where 
		tovar.Kod = zena.Kod
	and
		Data =  "2002 - 12 - 30 "
group by tovar.Kod;

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

2. если тебе нужен запрос, который тебе выдает - были ли изменения по цене у товаров за данную дату, то тоже никаких проблем:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
select
		tovar.Name,
		if(ISNULL(zena.Price),  "Нет изменений" , zena.Price) as Price,
		 "2002 - 12 - 31 " as Data
from 
		tovar
left join
		zena
	on
			tovar.Kod = zena.Kod
		and
			Data =  "2002 - 12 - 31 ";


3. если тебе нужен запрос, который выберет ближайшее изменение к этой дате, то лично у меня возникли проблемы, которые я решил таким способом:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select
		tovar.Name,
		min(CONCAT(ABS(to_days(zena.Data)-to_days( "2003 - 02 - 03 ")),  "0101010101 ", zena.Price)) as _diff,
		Data
from 
		zena,
		tovar
where 
		tovar.Kod = zena.Kod
group by tovar.Kod;


только придется выделять на стороне клиента цену из поля diff (разделитель, в моем случае, 0101010101. он должен быть числовым).

4. Если чего то еще, то пиши

Удачи.
...
Рейтинг: 0 / 0
01.04.2003, 19:18
    #32131341
medved
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
P.S. Четверка, то вроде уже не сырая, покрайней версия 4.012 (источник новость на MySQL.com) рекомендованна к использованию.... Вот только вложенных запросов в ней попрежнему нету. :(

P.S. Последний пример: мона разбивать и в Мускуле (чего то мысля дальше не пошла :( ), и такой пример описываеться в доке на все том же MySQL.com
http://www.mysql.com/doc/ru/example-Maximum-column-group-row.html и назван не эффективным... :(. Ну это я и сам знал.
...
Рейтинг: 0 / 0
01.04.2003, 19:37
    #32131356
medved
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
P.P.P.S чего-то Артем разошелся.... Два вложенных запроса.... Ни есть гуд.
...
Рейтинг: 0 / 0
02.04.2003, 12:00
    #32131665
BigHarry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
(2) medved
Что-то не получается...
Мне нужна возможность получать цену по товарам на определенную дату (дата задается юзером).
Я попробовал твой третий вариант, но почему-то он выдает неправильный результат:
Имеется такая запись в таблице Zena
Код: plaintext
1.
2.
3.
INSERT INTO Zena VALUES ('5730', '2002-12-31',  11290 );
INSERT INTO Zena VALUES ('5730', '2003-01-06',  11790 );
INSERT INTO Zena VALUES ('5730', '2003-02-05',  12190 );


Что бы узнать цену на дату 03-02-2003 (цена должна быть 11790) запрос:
select tovar.Name, min(CONCAT(ABS(to_days(zena.Data)- to_days("2003-02-03")), "0101010101", zena.Price)) as _diff, Data from zena, tovar
where tovar.kod='5730' AND (tovar.Kod = zena.Kod) group by tovar.Kod;
возвращает значение 12190, а такое значение цены должно быть позжее.
Может - как-то извратиться с временной выборкой?
...
Рейтинг: 0 / 0
02.04.2003, 12:38
    #32131705
BigHarry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Странно, но правильный результат выдает следующий запрос (искомая дата - 01.02.2003):
Код: plaintext
1.
2.
3.
SELECT tovar.Name, zena.Price
FROM tovar,zena 
WHERE zena.Data <=  "2003 - 02 - 01 " AND (zena.Kod = tovar.Kod)
GROUP by tovar.Kod
...
Рейтинг: 0 / 0
02.04.2003, 13:45
    #32131800
medved
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Моя таблица zena

Kod  Data  Price
5618  2002-12-30  900  
5618  2003-01-25  920  
5618  2003-03-02  950  
1077  2002-12-30  750  
1077  2003-02-18  800  
3388  2002-12-30  6580  
3388  2003-01-15  7200  
3388  2003-03-02  7000  
5730  2002-12-31  11290  
5730  2003-01-06  11790  
5730  2003-02-05  12190  

Твой запрос
Код: plaintext
1.
2.
3.
SELECT tovar.Kod, tovar.Name, zena.Price
FROM tovar,zena 
WHERE zena.Data <=  "2003 - 02 - 01 " AND (zena.Kod = tovar.Kod)
GROUP by tovar.Kod


результат твоего запроса

Kod  Name  Price
1077  Чайник Скарлет-1022  750  
3388  Телевизор Sony E-25  6580  
5618  Утюг PHILIPS-78  900  

Для товара с кодом 5618 цена ближайшая по дате к к дате "2003-02-01",
"920" за дату 2003-01-25. Твой запрос выводит не эту, он выводит первую запись с датой меньше чем ты задал

Мой запрос
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
select
		tovar.Name,
		min(CONCAT(ABS(to_days(zena.Data)-to_days( "2003 - 02 - 01 ")),  "0101010101 ", zena.Price)) as _diff
from 
		zena,
		tovar
where 
		tovar.Kod = zena.Kod
group by tovar.Kod;


результат моего запроса

Name    _diff
Чайник Скарлет-1022    170101010101 800   
Телевизор Sony E-25    17010101010 17200   
Утюг PHILIPS-78    290101010101 950   

Проверяем:

Код товара 3388 ближайшая по дате цена 7200 за 2003-01-15
Код товара 5618 ближайшая по дате цена 920 за 2003-01-25
Код товара 1077 ближайшая по дате цена 800 за 2003-02-18

Я поставил там abs для того что бы считало как и после заданой даты так и до... Если тебе надо ближайшая цена с датой меньше заданной надо

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
select
		tovar.Name,
		min(CONCAT(ABS(to_days(zena.Data)-to_days( "2003 - 02 - 01 ")),  "0101010101 ", zena.Price)) as _diff
from 
		tovar
left join
		zena
	on
			tovar.Kod = zena.Kod
		and
			zena.Data< "2003 - 02 - 01 "
group by tovar.Kod
order by tovar.Kod


А мой запрос у меня лично не работает потому что у меня нет товара с кодом
5730... Как только я его добавил все появилось.
...
Рейтинг: 0 / 0
02.04.2003, 13:47
    #32131805
medved
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
"А мой запрос у меня лично не работает потому что у меня нет товара с кодом
5730... Как только я его добавил все появилось." - я хотел сказать что вот этот запрос не работает:

select tovar.Name, min(CONCAT(ABS(to_days(zena.Data)- to_days("2003-02-03")), "0101010101", zena.Price)) as _diff, Data from zena, tovar
where tovar.kod='5730' AND (tovar.Kod = zena.Kod) group by tovar.Kod;
...
Рейтинг: 0 / 0
02.04.2003, 14:18
    #32131846
BigHarry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Да - мой запрос лажает...
Твой, который последний - похоже то, что нужно, вот только столбец, который он возвращает - какой-то некузявный - из него ещо надо каким-то макаром вычипить цену...
Пойду гляну в ману - надо же хоть до чего-то самому допереть...
...
Рейтинг: 0 / 0
02.04.2003, 14:33
    #32131864
BigHarry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Сделал так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
SELECT tovar.Name,
MIN(CONCAT(ABS(to_days(zena.Data)-to_days( "2003 - 02 - 01 ")),  "0101010101 #", zena.Price)) as _diff
FROM tovar
LEFT JOIN zena ON tovar.Kod = zena.Kod AND zena.Data< "2003 - 02 - 01 "
group by tovar.Kod
HAVING _diff != ""
ORDER BY tovar.Name

Вроде - все нормально - теперь цену можно отделить по поиску подстроки #
Блин, хочется что бы цену в нормальном виде не на клиенте обрабатывать, а получать в виде числа с сервера, иначе - тормозит...

А каким запросом можно скинуть цены на определенную дату во временную таблицу (при условии что дата цены меньше или равна требуемой даты)?
...
Рейтинг: 0 / 0
02.04.2003, 14:34
    #32131866
medved
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Ну если пхп
то где-нидь так:
Код: plaintext
1.
2.
list($data_diff, $price) = explode( "0101010101 ", $db->result($result,  0 , '_diff'));
echo $price;
...
Рейтинг: 0 / 0
02.04.2003, 14:44
    #32131881
BigHarry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Не - не для пхп, надо как столбец в Дельфи, и тама должно быть число...
...
Рейтинг: 0 / 0
02.04.2003, 15:48
    #32131951
BigHarry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Нифига не получаеться!
Помогите, плиз, как мне сделать выборку в другую таблицу, типа так:
Код: plaintext
1.
2.
3.
4.
SELECT INTO temptable UNIQUE(zena.Kod), zena.Data, zena.Price
FROM zena 
WHERE zena.Data <=  "2003 - 02 - 01 "
ORDER BY Kod, Data DESC
...
Рейтинг: 0 / 0
02.04.2003, 18:30
    #32132190
medved
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
select
		tovar.Name,
		SUBSTRING(
							min(CONCAT(ABS(to_days(zena.Data)-to_days( "2003 - 02 - 01 ")),  "12345678987654321 ", zena.Price)), 
							 17 +LOCATE(
												 "12345678987654321 ", 
												min(
														CONCAT(
																		ABS(to_days(zena.Data)-to_days( "2003 - 02 - 01 ")), 
																		 "12345678987654321 ", 
																		zena.Price)
													)
									)
		) as _diff
from 
		tovar
left join
		zena
	on
			tovar.Kod = zena.Kod
		and
			zena.Data< "2003 - 02 - 01 "
group by tovar.Kod
order by tovar.Kod


Ну теперь в поле _price цена товара
...
Рейтинг: 0 / 0
03.04.2003, 13:57
    #32132718
BigHarry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Я уже выкрутился, через темповую таблу. Хотел сначала через строковые функции, как ты и предложил, но выражение получалось запарно-длинное - я подумал, что Мускуль быстрее с темповой таблой прокрутится...
Вот что получилось:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
CREATE TEMPORARY TABLE pricetmp (Kod CHAR( 4 ) NOT NULL,
Price SMALLINT( 5 ) UNSIGNED NOT NULL,
FakeNum SMALLINT( 3 ) UNSIGNED NOT NULL,
PRIMARY KEY (Kod));

INSERT INTO pricetmp SELECT zena.Kod, zena.Price,
MIN(to_days(NOW())-to_days(zena.Data)) AS sex
FROM zena
WHERE zena.Data <= NOW()
GROUP BY Kod;

SELECT tovar.Name,
IFNULL(pricetmp.Price, 0 ) AS Price
FROM tovar
LEFT JOIN pricetmp ON pricetmp.Kod=tovar.Kod
WHERE tovar.Folder='0'
GROUP BY tovar.Kod;
...
Рейтинг: 0 / 0
04.04.2003, 17:09
    #32133874
Chira
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Один SQL:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
select t.*,z1.kod,max(z1.data),z2.data,z2.price
from zena z1, zena z2, tovar t
where z1.kod = z2.kod and z1.data <= '2003-02-03' and z2.data <= '2003-02-03'
	and t.kod = z1.kod
group by z1.kod,z2.data, z2.price
having z2.data = MAX(z1.data)
;

через TEMP таблицу будет быстрее
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
CREATE TEMPORARY TABLE pricetmp
TYPE=HEAP
SELECT Kod, MAX(Data)
FROM zena
WHERE Data <= NOW()
GROUP BY Kod;

SELECT tovar.Name,
IFNULL(zena.Price, 0 ) AS Price
FROM tovar
LEFT JOIN pricetmp ON pricetmp.Kod=tovar.Kod
LEFT JOIN zena ON pricetmp.Kod=zena.Kod AND pricetmp.data=zena.data
WHERE tovar.Folder='0'
...
Рейтинг: 0 / 0
04.04.2003, 17:52
    #32133913
BigHarry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
Проверил - первый запрос вааще ничего не возвращает - ошибки нет, но и выборка пуста, а второй - почти такой-же, как и у меня, только - у меня ещо индекс построен по коду в темповой таблице, иначе LEFT JOIN минуты две-три выстраивается, и при этом ресурсы мускуль начинает отжирать...
...
Рейтинг: 0 / 0
04.04.2003, 18:13
    #32133938
Chira
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
первый запрос для приведенных здесь данных на дату 2003-02-03
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
+ ------+---------------------+------+--------------+------------+-------+
 
| Kod  | Name                | kod  | max(z1.data) | data       | price |
+ ------+---------------------+------+--------------+------------+-------+
 
|  1077  | Чайник Скарлет- 1022  |  1077  |  2002 - 12 - 30    |  2002 - 12 - 30  |    750  |
|  3388  | Телевизор Sony E- 25  |  3388  |  2003 - 01 - 15    |  2003 - 01 - 15  |   7200  |
|  5618  | Утюг PHILIPS- 78      |  5618  |  2003 - 01 - 25    |  2003 - 01 - 25  |    920  |
+------+---------------------+------+--------------+------------+-------+

Насчет второго варианта - временная таблица создается как HEAP (в памяти), следовательно индексы для нее не нужны.
Если у тебя большой объем данных (в память не влезет), то нужно пересмотреть конструкцию.
...
Рейтинг: 0 / 0
17.07.2003, 12:18
    #32210741
BigHarry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая выборка из двух таблиц
В общем - обломился - мой вариант не дает правильных данных.
Что бы эта ветка никого не ввела в заблуждение и кто-то не напоролся на грабли, вот правильный запрос:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
CREATE TEMPORARY TABLE pricetmp (Kod CHAR( 4 ) NOT NULL,
Price SMALLINT( 5 ) UNSIGNED NOT NULL,
PRIMARY KEY (Kod));

INSERT INTO pricetmp SELECT Kod, Price
FROM zena WHERE Data <= NOW()
ORDER BY Kod, Data DESC;


В данном случае в темпоральную таблицу будут вставляться данные в порядке возрастания дат, а поскольку код является примари - то вставить более чем одной записи с кодом мускуль не даст.
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Хитрая выборка из двух таблиц / 23 сообщений из 23, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]