
Vai to var izdarīt ar SELECT? Kā?
Moderatori: janis.wd, Vecākie lietotāji
Code: Select all
select goods.id, name, price FROM goods
LEFT JOIN Price ON goods.id = Price.id_good
where `when` IN ( select max(`when`) FROM Price where id_good = goods.id )
group by goods.id
order by `when` desc
Tam ir nepieciešoms izmantot server side vai program side kodu. SQL ir datu bāzes serveris ne apstrādes...ob1 wrote:Pag, veči, uzdevumā ir prasīts atgriezt 3 laukus - id, name un price. Nu labi, var būt arī papildus lauki, bet vismaz tie 3.
Code: Select all
SELECT Goods.id, Goods.name, Price.price FROM Price INNER JOIN Goods ON Price.id_good = Goods.id WHERE Goods.id='$id' AND Price.when< ='date("d.m:Y H:i")' ORDER BY Price.when DESC LIMIT 1;
Jā tiešam lohs, kam``````````````````````domāts?usver wrote:btw, WHEN sql`os mēdz būt rezervētais vārds, tāpēc to vaig pārsaukt savādāk, kamēr vēl top. bet atkal - ko es, l**s, te mācu ūbervečus, kas laikam SQL`u dzen uz paštaisītas DBVS..
rATRIJS wrote:pag pag Andress - gribi teikt, ka kvērijos nevar izmantot JOIN'us, jo tas ir lēni?![]()
![]()
un rezervētos vārdus tiešām nav vēlams izmantot, jo tas palielina varbūtību uz visādiem bugiem (ar visām pēdiņām)
un jā - manā augstāk redzamajā postā ir ar visu join'u
Muaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahahaha1oneleven11111!!111111 :DDD tu zini cik daudz texta datu ietilpst 12Gb?usver wrote:esmu darbojies ar 12GB datubāzēm.
JOIN iebremzē, iebremzē, pabenčmarko kautway ar dummy datiem iekš sqlob1 wrote:->Andress
Vispār jau JOIN nebremzē, ja vien WHERE klauze ir optimizējama un ir pareizi salikti indeksi.
A par tiem mainīgajiem, kādām vērtībām tur ir jābūt?
Tu jocīgs esi? nafik full table scan darīt, maļot cauri visu saturu? Speciāli priekš tā ir radīti indeksi - lai nav jāpārlasa viss datubāzes saturs pie katra WHERE.Andress wrote:Zini ka ar izpildes atrumu 100mbps tavs query pildisies kkur 20min?usver wrote:esmu darbojies ar 12GB datubāzēm.
Code: Select all
SELECT Goods.id, MAX(Price.when) as when;
FROM goods ;
LEFT JOIN price ON Goods.id = Price.id_good;
GROUP BY Goods.id ;
INTO CURSOR tc_1
SELECT tc_1.id, goods.name, price.price ;
FROM tc_1 ;
LEFT JOIN goods ON tc_1.id = goods.id ;
LEFT JOIN price ON tc_1.id = price.id_good AND tc_1.when = price.when ;
INTO CURSOR tc_2
Code: Select all
create table goods (
god_id int not null primary key,
name varchar(50) not null
);
create table prices (
prc_id int not null primary key,
prc_god_id int not null,
price float,
prc_time datetime
);
insert into goods values (1, 'aaa');
insert into goods values (2, 'bbbb');
insert into goods values (3, 'ccc');
insert into goods values (4, 'ddd');
insert into goods values (5, 'eee');
insert into goods values (6, 'fff');
insert into goods values (7, 'ggg');
insert into goods values (8, 'hhh');
insert into goods values (9, 'iii');
insert into goods values (10, 'jjj');
insert into prices values (1, 1, 10, now());
insert into prices values (2, 1, 20, now()-100);
insert into prices values (3, 1, 30, now()-200);
insert into prices values (4, 2, 30, now());
insert into prices values (5, 2, 20, now()-100);
insert into prices values (6, 2, 10, now()-200);
insert into prices values (7, 3, 10, now());
insert into prices values (8, 3, 20, now()-100);
insert into prices values (9, 4, 20, now());
insert into prices values (10, 4, 10, now()-100);
insert into prices values (11, 5, 10, now());
insert into prices values (12, 6, 10, now());
insert into prices values (13, 7, 10, now());
insert into prices values (14, 7, 20, now());
insert into prices values (15, 8, 20, now());
insert into prices values (16, 9, 20, now());
insert into prices values (17, 10, 20, now());
alter table prices add constraint prc_god_fk foreign key (prc_god_id)
references goods(god_id);
Code: Select all
insert into goods select god_id + 10, name from goods;
insert into goods select god_id + 20, name from goods;
insert into goods select god_id + 40, name from goods;
insert into goods select god_id + 80, name from goods;
insert into goods select god_id + 160, name from goods;
insert into goods select god_id + 320, name from goods;
insert into goods select god_id + 640, name from goods;
insert into goods select god_id + 1280, name from goods;
insert into goods select god_id + 2560, name from goods;
insert into goods select god_id + 5120, name from goods;
insert into goods select god_id + 10240, name from goods;
insert into goods select god_id + 20480, name from goods;
insert into goods select god_id + 40960, name from goods;
insert into prices
select prc_id + 20, prc_god_id + 10, price, prc_time from prices;
insert into prices
select prc_id + 40, prc_god_id + 20, price, prc_time from prices;
insert into prices
select prc_id + 80, prc_god_id + 40, price, prc_time from prices;
insert into prices
select prc_id + 160, prc_god_id + 80, price, prc_time from prices;
insert into prices
select prc_id + 320, prc_god_id + 160, price, prc_time from prices;
insert into prices
select prc_id + 640, prc_god_id + 320, price, prc_time from prices;
insert into prices
select prc_id + 1280, prc_god_id + 640, price, prc_time from prices;
insert into prices
select prc_id + 2560, prc_god_id + 1280, price, prc_time from prices;
insert into prices
select prc_id + 5120, prc_god_id + 2560, price, prc_time from prices;
insert into prices
select prc_id + 10240, prc_god_id + 5120, price, prc_time from prices;
insert into prices
select prc_id + 20480, prc_god_id + 10240, price, prc_time from prices;
insert into prices
select prc_id + 40960, prc_god_id + 20480, price, prc_time from prices;
insert into prices
select prc_id + 100000, prc_god_id + 40960, price, prc_time from prices;
Code: Select all
mysql> explain
-> select q.prc_god_id, price, name
-> from goods
-> inner join prices
-> on (god_id = prc_god_id)
-> inner join (
-> select prc_god_id, max(prc_time) max_prc_time
-> from prices
-> group by prc_god_id) q
-> on (prices.prc_god_id = q.prc_god_id
-> and prices.prc_time = q.max_prc_time);
+----+-------------+------------+--------+---------------+------------+---------+--------------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+------------+---------+--------------+--------+-------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 81920 | |
| 1 | PRIMARY | goods | eq_ref | PRIMARY | PRIMARY | 4 | q.prc_god_id | 1 | |
| 1 | PRIMARY | prices | ref | prc_god_fk | prc_god_fk | 4 | q.prc_god_id | 8 | Using where |
| 2 | DERIVED | prices | index | NULL | prc_god_fk | 4 | NULL | 139664 | |
+----+-------------+------------+--------+---------------+------------+---------+--------------+--------+-------------+
Code: Select all
mysql> select sum(price) from (
-> select q.prc_god_id, price, name
-> from goods
-> inner join prices
-> on (god_id = prc_god_id)
-> inner join (
-> select prc_god_id, max(prc_time) max_prc_time
-> from prices
-> group by prc_god_id) q
-> on (prices.prc_god_id = q.prc_god_id
-> and prices.prc_time = q.max_prc_time)
-> )q1;
+------------+
| sum(price) |
+------------+
| 1474560 |
+------------+
1 row in set (3.67 sec)
Code: Select all
mysql> create index prc_idx on prices (prc_god_id, prc_time, price);
Query OK, 139264 rows affected (7.45 sec)
Records: 139264 Duplicates: 0 Warnings: 0
Code: Select all
mysql> explain
-> select q.prc_god_id, price, name
-> from goods
-> inner join prices
-> on (god_id = prc_god_id)
-> inner join (
-> select prc_god_id, max(prc_time) max_prc_time
-> from prices
-> group by prc_god_id) q
-> on (prices.prc_god_id = q.prc_god_id
-> and prices.prc_time = q.max_prc_time);
+----+-------------+------------+--------+---------------+---------+---------+-----------------------------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+-----------------------------+--------+-------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 81920 | |
| 1 | PRIMARY | goods | eq_ref | PRIMARY | PRIMARY | 4 | q.prc_god_id | 1 | |
| 1 | PRIMARY | prices | ref | prc_idx | prc_idx | 13 | q.prc_god_id,q.max_prc_time | 1 | Using index |
| 2 | DERIVED | prices | index | NULL | prc_idx | 18 | NULL | 130928 | Using index |
+----+-------------+------------+--------+---------------+---------+---------+-----------------------------+--------+-------------+
Code: Select all
mysql> select sum(price) from (
-> select q.prc_god_id, price, name
-> from goods
-> inner join prices
-> on (god_id = prc_god_id)
-> inner join (
-> select prc_god_id, max(prc_time) max_prc_time
-> from prices
-> group by prc_god_id) q
-> on (prices.prc_god_id = q.prc_god_id
-> and prices.prc_time = q.max_prc_time)
-> )q1;
+------------+
| sum(price) |
+------------+
| 1474560 |
+------------+
1 row in set (3.00 sec)
Code: Select all
SELECT Goods.id, Goods.name, Price.price;
FROM ;
data1!goods ;
LEFT OUTER JOIN data1!price ;
ON Goods.id = Price.id_good;
WHERE Price.when IN (select max(when) from price where id_good=goods.id);
ORDER BY Goods.id
Code: Select all
SELECT Goods.id, MAX(Price.when) as when;
FROM goods ;
LEFT JOIN price ON Goods.id = Price.id_good;
GROUP BY Goods.id ;
INTO CURSOR tc_1
SELECT tc_1.id, goods.name, price.price ;
FROM tc_1 ;
LEFT JOIN goods ON tc_1.id = goods.id ;
LEFT JOIN price ON tc_1.id = price.id_good AND tc_1.when = price.when ;
INTO CURSOR tc_2
Jā varēt var vienu no N plāniem, kas šķiet acīmredzmākais. Taču nekad par to nevari būt drošs, ja vien neziniob1 wrote: 1) Selekta ātrumu VAR novērtēt "uz aci", ja vien ir zināšanas un pieredze.
Izpildes plānu var noemulēt galvā - šie selekti nav pārāk sarežģīti.
Starp citu vai Tu paskatījies manis doto variantu? Tur nav apakšvaicājumu. Tur tie netiks pildīti katru reizi katrai virsselketā atlasītajai rindiņai.ob1 wrote: 2) Analizējot viena selekta gadījumu, skaidri redzams, ka apakšselekts izpildīsies katrai galvenā selekta ierakstam atsevišķi.
Pilnīgi skaidri redzams, ka bremze būs... un paldies Tev, ka tagad zinu cik liela tā bremze ir.
Code: Select all
mysql> explain
-> select prc_god_id, price, name
-> from goods
-> left outer join prices
-> on prc_god_id = god_id
-> where prc_time in (
-> select max(prc_time) from prices where prc_god_id = goods.god_id)
-> order by god_id;
+----+--------------------+--------+------+---------------+---------+---------+-------------------+-------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+--------+------+---------------+---------+---------+-------------------+-------+--------------------------+
| 1 | PRIMARY | goods | ALL | PRIMARY | NULL | NULL | NULL | 82370 | Using filesort |
| 1 | PRIMARY | prices | ref | prc_idx | prc_idx | 4 | test.goods.god_id | 1 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | prices | ref | prc_idx | prc_idx | 4 | test.goods.god_id | 1 | Using index |
+----+--------------------+--------+------+---------------+---------+---------+-------------------+-------+--------------------------+
mysql> select sum(price) from (
-> select prc_god_id, price, name
-> from goods
-> left outer join prices
-> on prc_god_id = god_id
-> where prc_time in (
-> select max(prc_time) from prices where prc_god_id = goods.god_id)
-> order by god_id) a;
+------------+
| sum(price) |
+------------+
| 1474560 |
+------------+
1 row in set (7.20 sec)
Gribēt nevienam, protams, nav aizliegts, bet uz mana konkrētā dzelža tas neiet cauri, jo tur vienkāršs sum aizņem 0.2 sek un sum no abu tabulu savienojuma pussekundi.ob1 wrote: 3) 3 sekundes pie tik maziem datubāzes izmēriem ir slikts rezultāts. Vajadzētu kādu 0.1 sekundi vai mazāk.
Code: Select all
select q.id_good, price, name ;
from goods ;
inner join price on (price.id_good = goods.id) ;
inner join ( ;
select id_good, max(when) max_when ;
from price ;
group by id_good) q ;
on (price.id_good = q.id_good ;
and price.when = q.max_when) ;
šozanah? kur ir ponts lietot INNER JOIN un sūdzēties, ka "atlasa tikai sakrītošos"? 0_o takš lieto LEFT JOIN, ja vajag!ob1 wrote:5) Varianti 1 un 3 rezultātos neiekļauj preci, kurai nav atbilstoša ieraksta tabulā 'price'.Code: Select all
inner join price on (price.id_good = goods.id) ; inner join .. ;
Bugs bija specifikācijā nevis kodā ;)ob1 wrote:usver, variantā nr. 2 es tā arī darīju... bet pārējos variantus neizdomāju es...
Bet bugs nr. 2 ir arī ar left join...
Code: Select all
select q.prc_god_id, max(price), name
from goods
left join prices
on (god_id = prc_god_id)
left join (
select prc_god_id, max(prc_time) max_prc_time
from prices
group by prc_god_id) q
on (prices.prc_god_id = q.prc_god_id
and prices.prc_time = q.max_prc_time)
group by prc_god_id, name;