Avatar billede kdjweb Nybegynder
30. januar 2010 - 13:56 Der er 13 kommentarer og
1 løsning

Problem med at tælle antal nye poster

Hej eksperter. Jeg har prøvet på alle tænkeligt måder, at få udregnet hvor mange ulæste poster der er, men det vil bare ikke lykkes for mig.

Systemet foregår sådan at man har muligheden for at skrive breve til andre hvori andre kan skrive i. f.eks. ligesom facebook.

Her er mine tabeller ser således ud
[code]CREATE TABLE IF NOT EXISTS `post` (
  `ID` int(11) NOT NULL auto_increment,
  `fra` int(11) NOT NULL,
  `til` int(11) NOT NULL,
  `title` varchar(255) NOT NULL,
  `text` text NOT NULL,
  `created` timestamp NOT NULL default NULL,
  `last_post_date` timestamp NOT NULL default NULL,
  PRIMARY KEY  (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

CREATE TABLE IF NOT EXISTS `post_beskeder` (
  `ID` int(11) NOT NULL auto_increment,
  `postID` int(9) NOT NULL,
  `text` text NOT NULL,
  `author` int(9) NOT NULL,
  `created` timestamp NULL default NULL,
  PRIMARY KEY  (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

CREATE TABLE IF NOT EXISTS `post_views` (
  `postID` int(11) NOT NULL,
  `userID` int(11) NOT NULL,
  `last_view` timestamp NULL default NULL,
  PRIMARY KEY  (`postID`,`userID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;[/code]

Det resultat jeg har brug for er, at tælle alle de poster hvor `post_views`.`last_view` er større end `post`.`last_post_date` OG hvor `post_views`.`user` =  '84' og `post`.`til` eller `post`.`fra` = '84'.

Alt jeg har brug for er et enkelt tal.
Avatar billede bauerdata Nybegynder
30. januar 2010 - 17:05 #1
Dette giver ingen mening eller ?
timestamp NOT NULL default NULL,
30. januar 2010 - 17:07 #2
Jamen jeg vil godt give et bud hvis jeg kan vaere sikker paa at jeg forstaar sammenhaengen.

Jeg gaar ud fra at du et eller andet sted har en tabel User med ID og navn og at de tal der staar i post.fra, post.til, post_beskedder.author, og post_views.userID refererer til id i User.

Saa gaar jeg ud fra at naar user 1 sender et nyt brev til user 2 saa oprettes der en ny linie i tabel post og post.created og post.lastpost timestamp fyldes ud med afsendelsestidspunktet.

Naar saa user 2 svarer paa brevet eller user 3 skriver i brevet saa oprettes der en ny linie i tabel post_beskeder.  post_beskedder.postID = post.ID for det brev der svares paa.  Baade post_beskedder.created og post.last_post_date fyldes ud med timestampet for afsendelsestidspunktet for beskedden.

Det forventes saa at userne vil holde oeje med beskedder paa de breve de har sendt eller modtaget.  Naar en bruger laeser beskedderne for et brev saa laves der en ny linie i tabellen post_views hvor post_views.postID = post.ID for det brev hvorfra beskedder laeses, post_views.userID = user.ID for den user der laeser, og post_views.last_view faar timestampte for det tidspunkt der laeses paa.

Er det alt sammen korrekt?  Hvis noget ikke er korrekt saa ret mig.  Det er vigtigt.

Saa vil du for en bestemt user taelle hvor mange beskedder der er sendt til de breve useren har sendt eller modtaget.  Du synes at definere en ulaest besked ved at post_views.last_view er stoerre end post.last_post_date.  Det virker overraskende, jeg ville have troet at det var omvendt, at hvis et brev havde beskedder med et STOERRE timestamt, altsaa senere, end timestampet for hvornaar useren har laset sidst saa har det brev ulaeste beskedder.  Venligst bekraeft at det er saadan.

Saa er der endnu et spoergsmaal.  Det sidste felt i post har typen timestamp men navnet last_post_date.  Det er da vel datoen og tiden for den sidste post der vises, ikke bare datoen.  Korrekt?

Og saa en kommentar:  Ved at taelle i hvor mange tilfaelde post.last_post_view er stoerre end post_view.last_view saa faar du ikke noedvendigvis antallet af ulaeste beskedder men antallet af breve der indeholder ulaeste beskedder.  Et brev kan velsagtens have modtaget mere end en besked siden useren laeste dem sidst.  Er det i orden bare at taelle hvormange breve har ulaeste beskedder?  Hvis du vil have antallet af ulaeste beskedder skal vi ogsaa ind og sammenligne med post_beskedder.created.

Det var mange ting - som du vel egenlig skulle have forklaret i dit spoergsmaal.  Jeg afventer dit svar, og hvis det er fyldestgoerende gaar jeg i gang med at udarbejde en loesning.
Avatar billede kdjweb Nybegynder
30. januar 2010 - 23:03 #3
Okay prøver lidt mere detaljeret. Forresten en fejl at der er en `text` col i `post` tabellen. Det bliver selfølgelig hentet fra `post_beskeder`.

Hvis vi har brugerene
[code]--- `users` ---
userID | username
1      | Gunnar
2      | Peter[/code]

Gunner skriver et brev til Peter, og det bliver indsat i tabellerne `post` og `post_beskeder`med værdierne:
[code]--- `post` ---
ID | fra | til | title | created            | last_post_date
1  | 1  | 2  | Test  | 2010-02-30 22:30:00 | 2010-02-30 22:30:00[/code]
[code]--- `post_beskeder` ---
ID | postID | text  | author | created
1  | 1      | Tester | 1      | 2010-02-30 22:30:00[/code]

Sammentidigt bliver Gunnar sat ind i `post_views`, da han ved hvad der er i tråden allerede.
[code]--- `post_views` ---
postID | userID | last_view
1      | 1      | 2010-02-30 22:30:00[/code]

5 minutter efter ser Peter så, at der er kommet en post fra Gunnar i hans indbakke, og han klikker ind på det. Når han så er inde på denne post, bliver der sat ind i `post_views:
[code]--- `post_views` ---
postID | userID | last_view
2      | 2      | 2010-02-30 22:35:00[/code]

Og når så Peter svarer så på Gunnars post, bliver `last_post_date` opdateret i `post` og der bliver indsat en ny række i `post_beskeder`. Herefter bliver `post_views` opdateret så vi ved, at Peter han har læst denne post.
[code]--- `post` --- UPDATE
ID | fra | til | title | created            | last_post_date
1  | 1  | 2  | Test  | 2010-02-30 22:30:00 | 2010-02-30 22:37:00[/code]
[code]--- `post_beskeder` ---
ID | postID | text  | author | created
2  | 1      | OK    | 2      | 2010-02-30 22:37:00[/code]
[code]--- `post_views` --- UPDATE
postID | userID | last_view
2      | 2      | 2010-02-30 22:37:00[/code]

Nu er Gunnars last_views altså ældre end `last_post_date` og derfor har han 1 ulæst post.

Håber det klarede det hele lidt mere op.

Og forresten

timestamp NOT NULL default NULL > Dette NULL betyder bare '0000-00-00 00:00:00'.
31. januar 2010 - 06:22 #4
Ja, det opklarede og korrigerede adskillige ting.

Men er der ikke et par trykfejl i din historie over Gunnar og Peter?  Der forekommer i fortaellingen kun et brev, det der er indfoert i post med ID = 1.  Skulle postID saa ikke have vaeret 1 i post_views klokken 22:35 og 22:37?  Hvis virkelig det at Peter klikker paa Gunnars brev skaber et nyt postID som ikke svarer til nogen ID i post saa haenger tabellerne ikke sammen og jeg vil ikke kunne lave SQL queries paa dem.

Saa er det vel saadan at efter at Peter klokken 22:37 har svaret paa Gunnars brev saa kan han klokken 22:38 sende endnu et svar: "Forresten jeg glemte at sige...".  Saa vil Gunnar have to ulaeste beskedder til sit brev.  Hvis vi sammenligner Gunnar's last_views med last_post_date saa faar vi tallet 1, at der er et brev med ulaeste beskedder.  Er resultatet 1 hvad du er ude efter, antallet af breve med ulaeste beskedder, eller er du noedt til at have resultatet 2, antallet af ulaeste beskedder?  Jeg spurgte om det samme i #2.  Jeg fik ikke svar, men det er helt essentielt at vaere klar paa dette punkt.

Saa lad mig faa dit svar paa disse to punkter saa jeg kan komme i gang.
Avatar billede bauerdata Nybegynder
31. januar 2010 - 08:47 #5
"Og forresten

timestamp NOT NULL default NULL > Dette NULL betyder bare '0000-00-00 00:00:00'."
Det giver fejl i min mysql
Avatar billede kdjweb Nybegynder
31. januar 2010 - 09:41 #6
Det skulle have været postID 1 ja beklager.
Det jeg er ude efter er antal af breve med ulæste beskeder.

Beklager det er et vanskeligt spørgsmål jeg har stillet.

bauerdata - virker i min. Og er ikke en fejl.
31. januar 2010 - 10:45 #7
I saafald skulle denne query virke, d.v.s. hvis det er bruger 1's ulaeste breve du vil have.  Hvis du kalder queryen for eksempel fra en php site vil du nok bruge en variabel for bruger og saa sige:  "...AND v.userID = $user.."

SELECT count(*)
FROM post p
JOIN post_views v ON p.ID=v.postID AND p.fra = v.userID OR p.til = v.userID AND v.userID = 1
WHERE p.last_post > v.last_view
GROUP BY p.ID

To kommentarer:  (1) Dit spoergsmaal var ikke vanskeligt da foerst vi havde overkommet vanskelighederne ved at kommunikere precist hvad spoergsmaalet var.

(2) Din tabelstruktur er meget for indviklet og med redundant data saasom tidspunktet for en begivenhed der bliver bevaret i tre forskellige tabeller.  Hvis det er noget du skal bruge serioest vil jeg anbefale at du opretter et nyt spoergsmaal saasom:  "Jeg har disse tabeller...." og genfortaelle Gunner og Peter historien (men med korrekte data) "...hvordan kan det forenkles?"
Avatar billede bauerdata Nybegynder
31. januar 2010 - 11:22 #8
Min mysql er
mysql  Ver 14.12 Distrib 5.0.75, for debian-linux-gnu (i486) using readline 5.2

Den fejler med


ERROR 1067 (42000) at line 2: Invalid default value for 'created'
31. januar 2010 - 13:30 #9
For test havde jeg lavet mine egne tabeller hvor querien virkede.  Saa omsatte jeg tabel- og kolonnenavnene til kdjweb's navne.  For nu at teste testen har jeg oprettet nye tabeller med identiske navne og med identiske data som i #3.  Men foer jeg kunne afproeve querien paany doede phpMyAdmin for mig (paa one.com).  Jeg har nu ventet en time for at se om den kom igen, men stadig ingen forbindelse.  Jeg vil nu kontakte one.com for at hoere hvad der er galt og saa vende tilbage naar der er liv.
31. januar 2010 - 16:01 #10
Saa virker mysql igen.

Jeg giver scriptet paa de tabeller jeg oprettede og de data jeg puttede i dem.  Med de tabeller og data giver det foelgende query resultatet 1 hvilket det skulle:

SELECT count(*)
FROM post p
JOIN post_views v ON p.ID=v.postID AND p.fra = v.userID OR p.til = v.userID AND v.userID = 1
WHERE p.last_post_date > v.last_view
GROUP BY p.ID

Tabeller og data:

CREATE TABLE post(ID INT, fra INT, til INT, titel VARCHAR(10), created DATETIME, last_post_date DATETIME);

CREATE TABLE post_beskeder(ID INT, postID INT, tekst VARCHAR(10), author INT, created DATETIME);

CREATE TABLE post_views(postID INT, userID INT, last_view DATETIME);

INSERT INTO post VALUES(1,1,2,'Test', '2010-01-30 22:30:00', '2010-01-30 22:37:00');
INSERT INTO post_beskeder VALUES(1,1,'Tester', 1, '2010-01-30 22:30:00');
INSERT INTO post_beskeder VALUES(2,1,'Ok', 2, '2010-01-30 22:37:00');
INSERT INTO post_views VALUES(1,1,'2010-01-30 22:30:00');
INSERT INTO post_views VALUES(1,2,'2010-01-30 22:35:00');
INSERT INTO post_views VALUES(1,2,'2010-01-30 22:37:00');
Avatar billede bauerdata Nybegynder
01. februar 2010 - 01:27 #11
Man kan helt droppe post_view

DROP TABLE IF EXISTS post;
CREATE TABLE post(ID INT, fra INT, til INT, titel VARCHAR(10), created DATETIME, last_post_date DATETIME);

DROP TABLE IF EXISTS post_beskeder;
CREATE TABLE post_beskedder(ID INT, postID INT, tekst VARCHAR(10), author INT, created DATETIME NOT NULL , viewed DATETIME NULL);

INSERT INTO post VALUES(1,1,2,'Test', '2010-01-30 22:30:00', '2010-01-30 22:37:00');
INSERT INTO post_beskeder (ID, postID, tekst, author, created) VALUES (1,1,'Tester', 1, NOW());
INSERT INTO post_beskeder (ID, postID, tekst, author, created) VALUES (2,1,'Ok', 2, NOW());
INSERT INTO post_beskeder (ID, postID, tekst, author, created) VALUES (3,1,'Tester', 1, NOW());
INSERT INTO post_beskeder (ID, postID, tekst, author, created) VALUES (4,1,'Tester', 2, NOW());
INSERT INTO post_beskeder (ID, postID, tekst, author, created) VALUES (5,1,'Tester', 1, NOW());


SELECT count(*)
FROM post_beskeder
WHERE PostId in (
    SELECT id
    FROM post
    WHERE '1' in (fra, til)
)
  AND viewed is NULL
  AND author != '1'


/*
Når der er en som læser en post_besked så skal viewed blot sættes til NOW()
*/
Avatar billede bauerdata Nybegynder
01. februar 2010 - 01:28 #12
c/post_beskeder/postbeskedder/

skeder kommer man knive og andre hårde ting i.
Avatar billede bauerdata Nybegynder
01. februar 2010 - 01:42 #13
Hvis du vil have de post som har ikke sete beskedder samt hvormange
kan du bruge denne
DROP TABLE IF EXISTS post;
CREATE TABLE post(ID INT, fra INT, til INT, titel VARCHAR(10), created DATETIME, last_post_date DATETIME);

DROP TABLE IF EXISTS post_beskedder;
CREATE TABLE post_beskedder(ID INT, postID INT, tekst VARCHAR(10), author INT, created DATETIME NOT NULL , viewed DATETIME NULL);

INSERT INTO post VALUES(1,1,2,'Test', '2010-01-30 22:30:00', '2010-01-30 22:37:00');
INSERT INTO post VALUES(2,1,2,'Test', '2010-01-30 22:30:00', '2010-01-30 22:37:00');
INSERT INTO post_beskedder (ID, postID, tekst, author, created) VALUES (1,1,'Tester', 1, NOW());
INSERT INTO post_beskedder (ID, postID, tekst, author, created) VALUES (2,1,'Ok', 2, NOW());
INSERT INTO post_beskedder (ID, postID, tekst, author, created) VALUES (3,1,'Tester', 1, NOW());
INSERT INTO post_beskedder (ID, postID, tekst, author, created) VALUES (4,1,'Tester', 2, NOW());
INSERT INTO post_beskedder (ID, postID, tekst, author, created) VALUES (5,1,'Tester', 1, NOW());
INSERT INTO post_beskedder (ID, postID, tekst, author, created) VALUES (1,2,'Tester', 1, NOW());
INSERT INTO post_beskedder (ID, postID, tekst, author, created) VALUES (2,2,'Ok', 2, NOW());


SELECT PostId, count(*)
FROM post_beskedder
WHERE PostId in (
    SELECT id
    FROM post
    WHERE '1' in (fra, til)
)
  AND viewed is NULL
  AND author != '1'
GROUP BY PostId
HAVING count(*) > 0

/*
Når der er en som læser en post_besked så skal viewed blot sættes til NOW()
*/
01. februar 2010 - 10:58 #14
kdjweb, bare lige den kommentar at det skuffer mig lidt.  Jeg mener at have gjort en indsats.  Maaske synes du ikke at det var noget.
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
Computerworld tilbyder specialiserede kurser i database-management

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