Avatar billede tblaster Nybegynder
24. november 2005 - 19:51 Der er 18 kommentarer og
1 løsning

Sql udtræk skal hente specifikke poster jævnfør relationer + krav

Hejsa

Jeg har et problem med et sql udtræk som jeg skal have lidt hjælp til at få rettet til. Jeg smider 200 point i puljen for at få en hurtig men også en rigtig løsning.

Lad os starte fra starten. Det hele funger på følgende måde:
1. Der vises en post i et system. Dette system har en unik id, "Origin". Når posten vises, gemmes der en information i "log" tabellen om at systemet har fået vist den pågælgende post. Denne post har et "ID".
2. Når systemet så skal have vist en ny post, skal den hente en post ud fra databasen der opfylder følgende:
    a. Posten må ikke have været vist i det pågælgende system før.
    b. Posten skal have en længe på max. MsgLength, det vil sige at følgende skal være opfyldt:
        LENGTH(D.Tekst) < " & MsgLength  &"
    c. Posten skal tilhøre en bestemet kategori, som er opfyldt i følgende sql:
        (D.ParentID = 0 " & Replace(FindIDer 13), "ParentID", "D.ParentID") & ")
    d. Udtrækket skal trække 50 tilfældige poster ud, og så sorter dem efter højeste score. (Det er her det volder de største problemer!)
   
Jeg benytter i dag nedensteådne sql. Jeg har dog 2 problemer med denne.
1. Et system får jævnligt vist en poste igen som den har haft vist før
2. ændre jeg limit til 20000 så får jeg en masse ens poster ud. Ved kørsel af et tilfældigt antal poster fik jeg 9 ens poster ud.

Sql = "SELECT* from (SELECT D.Tekst, D.ID, D.Score/D.Stemmer as Point FROM Data D LEFT JOIN Log S ON D.ID = S.DataID Where (S.DataID IS NULL or S.Origin <>'" & RQ_origin & "') and LENGTH(D.Tekst) < " & MsgLength  &" and (D.ParentID = 0 " & Replace(FindIDer(13), "ParentID", "D.ParentID") & ") Order By RAND() Limit 50) as tmpTable order by Point desc"

For mig er det fint bare at få rettet ovenstående sql til, men det er også fint at bygge den op fra bunden. Og hvis du mangler nogle info så spørg endelig.

Her er mine create scripts til mine tabeller, der gerne skulle give jer et indblik i min database:

CREATE TABLE `data` (
  `Id` int(11) NOT NULL auto_increment,
  `ParentID` int(4) NOT NULL default '0',
  `Navn` text,
  `Tekst` text NOT NULL,
  `Sprog` text NOT NULL,
  `Dato` datetime default NULL,
  `Score` int(11) NOT NULL default '6',
  `Stemmer` int(11) NOT NULL default '1',
  `Hits` int(11) NOT NULL default '0',
  `Aktiv` char(1) NOT NULL default '',
  PRIMARY KEY  (`Id`),
  KEY `ParentID` (`ParentID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=43861 ;

CREATE TABLE `log` (
  `ID` int(11) NOT NULL auto_increment,
  `Keyword` varchar(20) NOT NULL default '',
  `Msg` text NOT NULL,
  `Origin` int(8) NOT NULL default '0',
  `DataID` int(8) NOT NULL default '0',
  `Dato` timestamp NOT NULL default CURRENT_TIMESTAMP,
  PRIMARY KEY  (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=273 ;
Avatar billede tblaster Nybegynder
24. november 2005 - 19:55 #1
Nåh ja ... her er lige en sql som den ser ud når den er genereret:

SELECT * from (SELECT D.Tekst, D.ID, D.Score/D.Stemmer as Point FROM Data D LEFT JOIN log S ON D.ID = S.DataID Where (S.DataID IS NULL or S.Origin <>'606') and LENGTH(D.Tekst) < 160 and (D.ParentID = 0 Or D.ParentID=14 Or D.ParentID = 15 Or  D.ParentID = 212 Or D.ParentID = 13) Order By RAND() Limit 50) as tmpTable order by Point desc
Avatar billede dr_chaos Nybegynder
25. november 2005 - 08:05 #2
jeg skal lige se om jeg har forstået noget ret.
I tabellen data ligger der x antal poster.
Når en post har været vist gemmes id fra data tabellen i Log tabellen i feltet DataID.
Er det korrekt ?
Hvis en post har været vist før så skal den ikke vises igen ?
Avatar billede fennec Nybegynder
25. november 2005 - 08:36 #3
Det må være noget i denne stil. Det er dog ikke alle versioner af MySQL der understøtter det:

select * from (select D.Tekst, D.ID, D.Score/D.Stemmer as Point from data d where d.id not in (select dataid from log where Origin<>'"& RQ_origin &"') and LENGTH(d.Tekst) < " & MsgLength  &" and "& (D.ParentID = 0 " & Replace(FindIDer 13), "ParentID", "D.ParentID") & ")
&" order by rand() limit 50) order by point desc
Avatar billede tblaster Nybegynder
25. november 2005 - 09:22 #4
dr chaos ... det er rigtigt, lige med den kommentar at det kun hvis en post har været vist i et givet system før, at der jo ligger en post i log tabellen.
Avatar billede tblaster Nybegynder
25. november 2005 - 09:29 #5
Til info køre jeg med MySQL 4.1.9.

Fennex det giver følgende fejl:
#1248 - Every derived table must have its own alias

Dog har jeg måtte rette sql strengen lidt til:
Sql = "SELECT * from (select D.Tekst, D.ID, D.Score/D.Stemmer as Point from data d where d.id not in (select dataid from log where Origin <> '"& RQ_origin &"') and LENGTH(d.Tekst) < " & MsgLength  &" and (D.ParentID = 0 " & Replace(FindIDer(13), "ParentID", "D.ParentID") & ") Order by rand() limit 50) order by Point desc"

Og lige en ekstra ting. Det er jo ikke alle poster der ligger i "Data" tabellen der har en relation i "Log" tabellen. Deres id, "DataID", kan kun findes i "Log" tabellen hvis posten har været vist i et af de mange systemer, "Origin", før. Derfor vil jeg mene at det giver problemer med følgende, som langt fra vil få alle poster ud:
Select dataid from log where Origin <> '"& RQ_origin &"'
Avatar billede fennec Nybegynder
25. november 2005 - 09:36 #6
Der skal lige et alias på sub-select:

Sql = "SELECT * from (select D.Tekst, D.ID, D.Score/D.Stemmer as Point from data d where d.id not in (select dataid from log where Origin <> '"& RQ_origin &"') as Sub1 and LENGTH(d.Tekst) < " & MsgLength  &" and (D.ParentID = 0 " & Replace(FindIDer(13), "ParentID", "D.ParentID") & ") Order by rand() limit 50) as sub2 order by Point desc"

"Select dataid from log where Origin <> '"& RQ_origin &"'" bliver ikke joinet. Det er en sub-select, så den skulle være god nok :o)
Avatar billede tblaster Nybegynder
26. november 2005 - 12:02 #7
Det giver følgende fejl:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as Sub1 and LENGTH( d . Tekst ) < 160 and ( D . ParentID = 0 Or D . ParentID = 1' at line 1
Avatar billede tblaster Nybegynder
03. december 2005 - 11:05 #8
Er der nogen der kan hjælpe?
Avatar billede dr_chaos Nybegynder
03. december 2005 - 11:09 #9
prøv med
Sql = "SELECT * from (select D.Tekst, D.ID, D.Score/D.Stemmer as Point from data d where d.id not in (select dataid from log where Origin <> '"& RQ_origin &"') and LENGTH(d.Tekst) < " & MsgLength  &" and (D.ParentID = 0 " & Replace(FindIDer(13), "ParentID", "D.ParentID") & ") Order by rand() limit 50)  order by Point desc"
Avatar billede tblaster Nybegynder
03. december 2005 - 11:12 #10
Min phpMyAdmin returner følgende:
#1248 - Every derived table must have its own alias
Avatar billede tblaster Nybegynder
03. december 2005 - 15:39 #11
Nu har jeg leget lidt med sql'en og fundet ud af at hvis jeg nøjes med følgende så får jeg ikke fejl:
SQL = "select D.Tekst, D.ID, D.Score/D.Stemmer as Point from data d where d.id not in (select dataid from log where Origin <> '"& RQ_origin &"') and LENGTH(d.Tekst) < " & MsgLength  &" and (D.ParentID = 0 " & Replace(FindIDer(13), "ParentID", "D.ParentID") & ") Order by rand() limit 50)"

Hvordan får jeg så lige delen med at den skal sorter efter point?
Avatar billede dr_chaos Nybegynder
03. december 2005 - 15:42 #12
måske :
SQL = "select D.Tekst, D.ID, D.Score/D.Stemmer as Point from data d where d.id not in (select dataid from log where Origin <> '"& RQ_origin &"') and LENGTH(d.Tekst) < " & MsgLength  &" and (D.ParentID = 0 " & Replace(FindIDer(13), "ParentID", "D.ParentID") & ") Order by rand() limit 50, Point desc)"
Avatar billede tblaster Nybegynder
03. december 2005 - 15:46 #13
Det giver:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Point desc )  LIMIT 0, 30' at line 1

Det er også vitgit at den først vælger 50 tilfældige poster. Og når disse så er valgt, skal disse så sorteres efter højeste score.
Avatar billede dr_chaos Nybegynder
03. december 2005 - 15:48 #14
prøv med :
SQL = "select D.Tekst, D.ID, D.Score/D.Stemmer as Point from data d where d.id not in (select dataid from log where Origin <> '"& RQ_origin &"') and LENGTH(d.Tekst) < " & MsgLength  &" and (D.ParentID = 0 " & Replace(FindIDer(13), "ParentID", "D.ParentID") & ") Order by rand() limit 50, D.Score/D.Stemmer desc)"
Avatar billede tblaster Nybegynder
03. december 2005 - 15:50 #15
Det giver:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'D.Score/D.Stemmer desc)' at line 1
Avatar billede tblaster Nybegynder
03. december 2005 - 15:52 #16
Med følgende giver den ikke fejl:
Sql = "SELECT * from (select D.Tekst, D.ID, D.Score/D.Stemmer as Point from data d where d.id not in (select dataid from log where Origin <> '"& RQ_origin &"') and LENGTH(d.Tekst) < " & MsgLength  &" and (D.ParentID = 0 " & Replace(FindIDer(13), "ParentID", "D.ParentID") & ") Order by rand() limit 50) as temptabel order by Point desc"

Vil lige prøve at teste det igennem og se om der stadig er fejl.
Avatar billede dr_chaos Nybegynder
03. december 2005 - 15:54 #17
Ok det kan være at denne her virker.
ivhertifald mit sidste forslag
SQL = "select D.Tekst, D.ID, D.Score/D.Stemmer as Point from data d where d.id not in (select dataid from log where Origin <> '"& RQ_origin &"') and LENGTH(d.Tekst) < " & MsgLength  &" and (D.ParentID = 0 " & Replace(FindIDer(13), "ParentID", "D.ParentID") & ") Order by rand(), Point desc limit 50)"
Avatar billede tblaster Nybegynder
17. december 2005 - 17:56 #18
Har testet det igennem og det ser ud til at det virker som det skal. Smid et svar og du skal få dine point! Og mange tak for hjælpen.
Avatar billede dr_chaos Nybegynder
17. december 2005 - 18:13 #19
svar :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester