» »

Prosim vas za pomoč pri mysql queryju

Prosim vas za pomoč pri mysql queryju

krenpac ::

Recimo, da imam spodnjo tabelo

id cena
1  1.2
2  3.4
3  1
4  2.3
.
.
.


Želel bi dobiti število vrstic (ali same vrstice), ki ustrezajo pogoju, da je skupna vsota cen manjša od neke vrednosti. Primer...
1. Če izberem, da je skupna vsota cen manjša od 1
Ne vrne nobene vrstice

2. Izberem, da je skupna vsota cen manjša od 2.3
Vrne 1. vrstico
id cena
1  1.2


3. izberem, da je skupna vsota cen manjša od 6 (1.2+3.4+1=5.6)
Vrne prve 3 vrstice
id cena
1  1.2
2  3.4
3  1


itd.

Namesto vračila vseh vrstic, bi bilo dovolj, da bi mi le povedal, koliko je skupno število vrstic (uporaba COUNT() oz COUNT(id)).
Sem nekaj poskušal s sum, count, having ampak žal še brez uspeha.

Kakršna koli pomoč bi bila dobrodošla (pa če se da, bi prosil za kakšen namig/rešitev brez gnezdene poizvedbe - performance je namreč precej pomemben).
  • spremenilo: krenpac ()

MrStein ::

Naj jih vrača po vrsti, brez lukenj? Toren ne sme vrniti prvo in tretjo vrstico (kar bi ustrezalo pogoju "skupna vsota cen manjša od 2.3")
Motiti se je človeško.
Motiti se pogosto je neumno.
Vztrajati pri zmoti je... oh, pozdravljen!

krenpac ::

Mora vračati po vrsti, brez da bi kakšno vmes izpustil (razvrstil bom z ORDER BY ampak zgoraj je primer da gre pač od 1., 2. 3. vrstica itd...). Če je skupna vsota manj kot 2.3, potem najprej pogleda 1. vrstico, vidi, da je cena 1.2 kar je manj kot 2.3, potem gre na 2. vrstico, kjer je 3.4, torej 1.2+3.4=4.6 kar je večje od 2.3 zato 2. vrstice več ne izpiše.

Mi je uspelo vse skupaj rešiti s s tem primerom ampak je zdaj težava, da v phpmyadmin deluje, me pa malo heca en framework, kjer pa query iz kode na linku ne deluje. PA malo me skrbi performance, ker kolikor sem na hitro preveril, preverja vse vrstice, čeprav imam ceno indeksirano, kar spet ni ok.

Zgodovina sprememb…

  • spremenilo: krenpac ()

no comment ::

set @lim := 5; 

select
    t1.id,
    t1.cena,
    t1.running_total
from (
    select
        t.id,
        t.cena,
        (
            select sum(x.cena)
            from table1 x
            where x.id <= t.id
        ) as running_total
    from table1 t
    order by t.id
) t1
where running_total < @lim;


da rezultat:
id	cena     running_total
1	1.2	     1.2
2	3.4	     4.6

smacker ::

Tole bo hitreje, ker nima nested queryev: http://sqlfiddle.com/#!9/2c9cf5/2
SET @vsota=0;
SELECT
  t.id,
  t.cena,
  @vsota + t.cena as 'vsota',
  @vsota := @vsota + t.cena
FROM tabela t
HAVING vsota <=5;

krenpac ::

smacker: Točno tako sem rešil, kot sem že zgoraj zapisal, a imam sedaj težavo, ker mi tak query ne deluje v enem frameworku, deluje pa mi brez težav v phpmyadmin. Moram še malo preveriti v čem je težava.

Zgodovina sprememb…

  • spremenilo: krenpac ()

MrStein ::

Verjetno ne uporabljaš prave sintakse ali parametrov za poganjanje skript.
Motiti se je človeško.
Motiti se pogosto je neumno.
Vztrajati pri zmoti je... oh, pozdravljen!

krenpac ::

Zgoraj sem sicer podal slabo poimenovanje. Cena je v bistvu KOLIČINA, potem pa imam še eno stolpec poimenovan s ceno.

Torej
id kolicina cena
1 0.1 10
2 0.4 13
3 0.3 11

In sedaj je query, ki ga želim izvesti, omejen z 2 podatkom, ceno, ki je večja ali manjša od neke vrednosti, ter količino, ki se v bistvu obnaša tako, kot sem zgoraj zapisal za ceno, ki bi jo moral že v štartu poimenovati s količino. Upam, da je jasno, kaj želim povedati, kljub tejle zmedi in neposrečenem poimenovanju. Rešitev sem si zamislil tako, da bi najprej pač izvedel nek kompliciran query, ki bi mi izpisal, koliko zadetkov ustreza količini (ki se sešteva tako kot je bilo zgoraj zapisano) in potem bi ustvaril 2., enostaven query, kjer bi bila pač omejitev le cena, torej cena > ali cena < od neke vrednosti ter bi dodal LIMIT 0, [vrednost iz prvega queryja]. Kakšna ideja, kako bi to izvedel najbolj učinkovito? Bo tako v redu, da najprej izvedem query, ki ga je zapisal smacker nata pa pač še ta enostaven query? Ali bi to lahko izvedel z enim querijem? Trenutno imam urejeno tako, da imam v queryju le omejitev cene nato pa potem s PHP zankov enostavno poberem podatke, ki ustrezajo tem seštevanju količine. Seveda vse deluje brez težav, a me skrbi zaradi performance. Na primer, recimo, da nekdo določi ceno 0EUR ($nekaj > 0EUR) potem bodo tem pogoju zadoščale vse vrstice v bazi in teh je lahko v bazi, ne vem, par milijonov... te potem skranim v $results in v zanki pač potem recimo uporabim le prvi dve, ker je recimo potem pogoj glde količine že izponjen (jasno zanko potem ustavim z break;). Torej, da še enkrat povzamem kaj me skrbi, če ni jasno. Hipotetično, imam query "SELECT nekaj, cena, količina FROM tabela WHERE cena > 0" zadetke shraim v polje $results, ki bo lahko imemo ogrooooomno zapisov, potem pa pač s PHP zanko izluščim ustrezne po količini, ker pogoja o "seštevajoči" količini ne znam vključiti že v query. A je zelo slabo, da imaš tako velik array? Kako je glede performance? Težava je res, ker bo lahko nekdo, ki bo za ceno zapisal 0EUR, ustvaril zelo velik array, čeprav bo (zaradi količine) recimo ustrezen le 1. zapis. Tko nekako, upam, da sem bil dovolj jasen. Pa kakršno koli keširanje odpade.

MrStein je izjavil:

Verjetno ne uporabljaš prave sintakse ali parametrov za poganjanje skript.


Vsekakor, moram še ugotoviti kje je napaka.

Zgodovina sprememb…

  • spremenilo: krenpac ()

krenpac ::

(se opravičujem za typote, odgovora žal ne morem več urediti)

krenpac ::

Glede frameworka sem že dobil rešitev (potrebno je bilo uporabiti transakcije & razbit query na 2 querija). Glede performance pa ne vem, kaj je bolje, bo potrebno zadevo še malo potestirati. Kakršni koli predlogi seveda dobrodošli.

Zgodovina sprememb…

  • spremenilo: krenpac ()

krenpac ::

Pa še nekaj me zanima, da ne bom zdaj odpiral nove teme, glede mysql transakcij. Torej, ko začnem transakcijo, je konec "veselice" za ostale uporabnike in se mysql baza zaklene za kakršne koli spremembe s strani ostalih uporabnikov, vse dokler prvi ne konča zadeve (zaključim s commit, če gre kaj narobe, pa rollback)? Si to pravilno predstavljam? Delam eno zadevo kjer je res nujno potrebno, da dokler se ne izvedejo vsi queriji enega uporabnika znotraj transakcije, da drug v bazo ne sme pisati ali česa spreminjati.

Zgodovina sprememb…

  • spremenilo: krenpac ()

krenpac ::

Smacker
SET @vsota=0;
SELECT
  t.id,
  t.cena,
  @vsota + t.cena as 'vsota',
  @vsota := @vsota + t.cena
FROM tabela t
HAVING vsota <=5;


Sem malo potestiral in ta query ne bo dober. Tule je primer zakaj ne http://sqlfiddle.com/#!9/377a3/1 Če je 1. vrednost večja kot max. določena pod HAVING (v primeru na linku sem dal 7), bi želel, da query ne vrne rezultata, ker pač 5 ni večje kot 7, a HAVING seveda to vrstico izpusti, ker ne ustreza pogoju in lepo nadaljuje po tabeli in izpisuje naslednje dokler je vse skupaj manjše od 5. V primeru na linku tako izpiše 2 vrstici. Pa sem spet na začetku :/ Še kakšen predlog?

Zgodovina sprememb…

  • spremenilo: krenpac ()

krenpac ::

Deluje pa z gnezdeno poizvedbo ampak ob vsaki gnezdeni poizvedbi me srce zaboli :8) tko da ne vem, trenutno imam na izbiro gnezdeno poizvedbo ali potencialno zelo velik array :| Eno in drugo je slabo.

https://goo.gl/4Uq8ss

Še kakšen predlog?

Zgodovina sprememb…

  • spremenilo: krenpac ()

no comment ::

Ti se za performance sekiraj potem, ko bo prišlo do problemov. Bolje malo počasneje in pravilno kot pa narobe.

In pri SQL-u ne predpostavljaj preveč kar na pamet kako hitro bo kak query deloval, če nimaš res ogromno kilometrine.


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[SQL] Pohitritev izpisa

Oddelek: Programiranje
252630 (1529) kuall
»

SQL backup import

Oddelek: Programiranje
8977 (779) meh
»

NUJNO!Algoritmi C++

Oddelek: Pomoč in nasveti
211868 (1130) DOOM_er
»

[SQL] Unikatni izpisi

Oddelek: Programiranje
212064 (1451) 111111111111
»

sql select stavek

Oddelek: Programiranje
121381 (1283) zavajon

Več podobnih tem