[mysql]Numerator wiersza / uniknięcie podwójnego ORDER BY
william - 13-11-2006 00:44
[mysql]Numerator wiersza / uniknięcie podwójnego ORDER BY
Schemat problemu wygląda mniej wiecej tak:
SELECT * FROM ( SELECT a, b, 1 AS priority FROM A ORDER BY a LIMIT ax OFFSET ay
UNION
SELECT a, b, 2 AS priority FROM B ORDER BY b LIMIT bx OFFSET by )
ORDER BY priority, a
Jak widać sortowanie było potrzebne w wewnętrznych selectach po to by wybrać właściwy przedział pewnych rekordów ze zbioru A i B. Zewnętrzny select ma mi je zwrócić w kolejności - najpierw blok A (o to dba "priority") a następnie według kolejności jaka była zastosowana w wewnętrznym selectcie. W Oracle dołączyłbym pseudokolumnę ROWNUM która numeruje po prostu po kolei wiersze wyniku każdego SELECTA. W MySQL szukam, szukam i nic podobnego nie mogę znaleść. Pseudokolumna _rowid jest związana fizycznie z tabelą a nie z wynikiem SQLa :(. Jeśli to tylko możliwe chciałbym uniknąć powtórnego sorotowania..... Proszę o pomysły.
keczerad - 13-11-2006 00:44
william napisał(a): > Schemat problemu wygląda mniej wiecej tak: > > SELECT * > FROM ( SELECT a, b, 1 AS priority > FROM A > ORDER BY a > LIMIT ax > OFFSET ay > > UNION > > SELECT a, b, 2 AS priority > FROM B > ORDER BY b > LIMIT bx > OFFSET by > ) > > ORDER BY priority, a > > > Jak widać sortowanie było potrzebne w wewnętrznych selectach po to by wybrać > właściwy przedział pewnych rekordów ze zbioru A i B. Zewnętrzny select ma mi > je zwrócić w kolejności - najpierw blok A (o to dba "priority") a następnie > według kolejności jaka była zastosowana w wewnętrznym selectcie. W Oracle > dołączyłbym pseudokolumnę ROWNUM która numeruje po prostu po kolei wiersze > wyniku każdego SELECTA. W MySQL szukam, szukam i nic podobnego nie mogę > znaleść. Pseudokolumna _rowid jest związana fizycznie z tabelą a nie z > wynikiem SQLa :(. Jeśli to tylko możliwe chciałbym uniknąć powtórnego > sorotowania..... Proszę o pomysły. > >
create view bez_sortowanie as
> SELECT * > FROM ( SELECT a, b, 1 AS priority > FROM A > LIMIT ax > OFFSET ay > > UNION > > SELECT a, b, 2 AS priority > FROM B > LIMIT bx > OFFSET by > ) > > ORDER BY priority, a
select * from bez_sortowanie Order by sortowanie
--
keczerad
http://www.e-mo.com.pl sklep w (X)HTML
Paweł Matejski - 13-11-2006 00:44
william wrote: > Schemat problemu wygląda mniej wiecej tak: > > SELECT * > FROM ( SELECT a, b, 1 AS priority > FROM A > ORDER BY a > LIMIT ax > OFFSET ay > > UNION > > SELECT a, b, 2 AS priority > FROM B > ORDER BY b > LIMIT bx > OFFSET by > ) > > ORDER BY priority, a > > > Jak widać sortowanie było potrzebne w wewnętrznych selectach po to by wybrać > właściwy przedział pewnych rekordów ze zbioru A i B. Zewnętrzny select ma mi > je zwrócić w kolejności - najpierw blok A (o to dba "priority") a następnie > według kolejności jaka była zastosowana w wewnętrznym selectcie. W Oracle > dołączyłbym pseudokolumnę ROWNUM która numeruje po prostu po kolei wiersze > wyniku każdego SELECTA. W MySQL szukam, szukam i nic podobnego nie mogę > znaleść. Pseudokolumna _rowid jest związana fizycznie z tabelą a nie z > wynikiem SQLa :(. Jeśli to tylko możliwe chciałbym uniknąć powtórnego > sorotowania..... Proszę o pomysły.
order by priority, case when priority = 1 then a else b end
-- P.M.
william - 13-11-2006 00:44
> > order by priority, case when priority = 1 then a else b end > > -- > P.M.
Nie wiem czy się dobrze zrozumieliśmy. ORDER + LIMIT / OFFSET mają za zadanie wyszukać np. 100 najbardziej aktualnych rekordów ze zbioru A i 50 ze zbioru B. Te warunki są niezależne. Potem jest union całośi i problem - jak sprawić by wynik całości się nie "rozsypał". Proponowane przez kolegów sortowanie w zewnętrznym SELECT da np. 150 rekordów ale tylko z tabeli A.
Paweł Matejski - 13-11-2006 00:44
william wrote: >> order by priority, case when priority = 1 then a else b end > > Nie wiem czy się dobrze zrozumieliśmy. ORDER + LIMIT / OFFSET mają za > zadanie wyszukać np. 100 najbardziej aktualnych rekordów ze zbioru A i 50 ze > zbioru B. Te warunki są niezależne. Potem jest union całośi
To z zapytania widać - tylko problem schowałeś w tekście w takim miejscu, które najmniej uważnie sie czyta (przedostatnie zdanie), do tego przykładając się ostro do kamuflażu (opisanie tego co i tak widać w zapytaniu i rozwiązania z oracla, które nie rozwiązuje problemu).
> i problem - jak > sprawić by wynik całości się nie "rozsypał".
Heh... Kolejny, który coś usłysz i tego używa, bo *wygląda*, że dana instrukcja robi to co on chce. Martwisz się o sortowanie 150 rekordów, a używasz instrukcji bez sprawdzenia w dokumentacji co ona robi. Na 99% każesz bazie robić niepotrzebną operacje, która dodatkowo w pewnych przypadkach może dać wynik inny niż potrzebujesz. Tego wszystkiego dowiedziałbyś się z dokumentacji, a przy okazji znalazł rozwiązanie swojego problemu.
P.S. Jakby znowu nie trafił w problem który masz, to opieprz za nieczytanie dokumentacji nigdy nie zaszkodzi! ;)
-- P.M.
william - 13-11-2006 00:44
> robi to co on chce. Martwisz się o sortowanie 150 rekordów, a używasz > instrukcji bez sprawdzenia w dokumentacji co ona robi. Na 99% każesz bazie > robić > niepotrzebną operacje, która dodatkowo w pewnych przypadkach może dać > wynik inny > niż potrzebujesz. Tego wszystkiego dowiedziałbyś się z dokumentacji, a > przy > okazji znalazł rozwiązanie swojego problemu.
Hmm, przeczytałem rozdział 13.2.7.2. (UNION Syntax) i nic nowego do mojej wiedzy nie wniósł ... SQL/95 wyraźnie mówi, że wynik każdego SELECTA może być zwrócony przez motor bazy w DOWOLNEJ kolejności. Ty piszesz że zewnętrzny order jest już niepotrzebny. Czy zatem MySQL daje gwarancję że UNION i podzapytania zachowają kolejność przetwarzanych wyników ??
Paweł Matejski - 13-11-2006 00:44
william wrote: >> robi to co on chce. Martwisz się o sortowanie 150 rekordów, a używasz >> instrukcji bez sprawdzenia w dokumentacji co ona robi. Na 99% każesz bazie >> robić >> niepotrzebną operacje, która dodatkowo w pewnych przypadkach może dać >> wynik inny >> niż potrzebujesz. Tego wszystkiego dowiedziałbyś się z dokumentacji, a >> przy >> okazji znalazł rozwiązanie swojego problemu. > > Hmm, przeczytałem rozdział 13.2.7.2. (UNION Syntax) i nic nowego do mojej > wiedzy nie wniósł ... SQL/95 wyraźnie mówi, że wynik każdego SELECTA może > być zwrócony przez motor bazy w DOWOLNEJ kolejności. Ty piszesz że > zewnętrzny order jest już niepotrzebny. Czy zatem MySQL daje gwarancję że > UNION i podzapytania zachowają kolejność przetwarzanych wyników ??
Nie. UNION nie tylko łączy zbiory, ale również pozbywa się duplikatów. A tą ostatnią operacje realizuję się przez posortowanie rekordów. A ponieważ tak naprawdę rzadko kto tego potrzebuje, a i z opisu wynika, że tego się nie spodziewasz, więc aby pozbyć się jednego sortowania wystarczy dodać słówko ALL. Dodatkowo UNION ALL nie ma powodów aby zmieniać kolejność więc zewnętrzne sortowanie powinno wykonać się szybko. Ale sortowanie zewnętrzne zostaw, bo niestety nikt nie gwarantuje takiego zachowania UNION ALL.
-- P.M.
william - 13-11-2006 00:44
> Dodatkowo UNION ALL nie ma powodów aby zmieniać kolejność więc zewnętrzne > sortowanie powinno wykonać się szybko. Ale sortowanie zewnętrzne zostaw, > bo > niestety nikt nie gwarantuje takiego zachowania UNION ALL.
Czyli z tym się zgodimy obaj :). Dzieki za podpowiedź co do optymalizacji "ALL". Ale raz jeszcze dla pewności zapytam - czy w MySQL istniej mechanizm numeratora wierszy podobny do ROWNUM w ORACLE ? Jest to po prostu ułatwienie - niezależnie od wariantu sortowania w wewnętrznych SQLach, w zewnętrznym zawsze jest ten sam, uniwersalny warunek ORDER. Było to takie eleganckie ....
zanotowane.pldoc.pisz.plpdf.pisz.pleffulla.pev.pl
|
[mysql] =?ISO-8859-2?Q?Za=E6mienie=2E=2E=2E_jak_wy=B6wietli=E6?==?ISO-8859-2?Q?=2E=2E=2E?=
[mysql] =?ISO-8859-2?Q?wielko=B6=E6_bazy_a_stabilno=B6=E6=2C?==?ISO-8859-2?Q?_podzia=B3_du=BFej_bazy_a_powi=B1zania_tabel?=
[MySQL] =?ISO-8859-2?Q?Wy=B6wietlenie_kolejnej_pozycji=2C_?==?ISO-8859-2?Q?jak=B1_mia=B3by_dany_rekord=2C_gdybym_czyta=B3 _?==?ISO-8859-2?Q?wg_konkretnych_kryteri=F3w=2E_Da_si=EA_=3F?=
[mysql 4.0.x] przenoszenie kolum =?ISO-8859-2?Q?mi=EAdzy_bazam?==?ISO-8859-2?Q?i_cd_=2E=2E=2E_?=
[MySQL] =?ISO-8859-2?Q?z=B3=B1czenie_tabeli_u=BFytkownik_i?==?ISO-8859-2?Q?_zdj=EAcia_z_wyborem_zdj=EAcia_domy=B6lnego?=
Gdzie MySQL 4.1, a gdzie 5.0?
[MySQL 4.0...4.1] zabezpieczenie przed =?ISO-8859-2?Q?jednoczesn?==?ISO-8859-2?Q?=B1_edycj=B1?=
[MS SQL] "set names" (mySQL) w MS SQL
[mysql 5.x] jak =?ISO-8859-2?Q?zrealizowa=E6_zapytanie=3F_cz?==?ISO-8859-2?Q?yli_podzapytanie_i_wi=EAcej_ni=BF_jeden_rz=B1? ==?ISO-8859-2?Q?d_wynik=F3w?=
MySQL - jak =?ISO-8859-2?Q?wyeksportowa=E6_zawarto=B6=E6_wie?==?ISO-8859-2?Q?lkiej_tabeli?=
zanotowane.pldoc.pisz.plpdf.pisz.plkfia-tek.keep.pl
Cytat
Decede mihi sole - nie zasłaniaj mi słonca. Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści Hoc fac - tak czyń. A tergo - od tyłu; z tyłu. I czarne włosy posiwieją. Safona |
|