Items tonen niet niet gelezen zijn
Zou er mij iemand kunnen helpen AUB.
Want ik kom er niet uit.
Ik heb een tabel "gebruikers"
vb
sleutel naam
987654321 Dirk Coppens
123456789 Test
Ik heb een tabel "gelezen" waarin user_id en een news_id in staat
vb :
User_id news_id
123456789 5
123456789 9
987654321 9
987654321 3
Ik heb nog een tabel met news
vb:
ID Title
2 Libya Gingerly Begins Seeking Economic but Not Pol...
3 Pressed by U.S., Pakistan Seizes a Taliban Chief
4 Francis, Still Hobbled, Will Give It Another Try
5 Most Support U.S. Guarantee of Health Care
6 Google Courts Small YouTube Deals, and Very Soon
7 A Laptop With Vista That Seems Just Like a Fully U
9 Opportunists in Somalia
Wat is nu mijn probleem.
In tabel gelezen staan de gelezen berichten per gebruiker.
Ik wil enkel de records tonen van een gebruiker die nog niet gelezen zijn.
Alvast bedankt
Edit:
Ik heb de titel aangepast van 'listing' naar 'Items tonen niet niet gelezen zijn'.
Zorg in het vervolg dat je een duidelijke titel meegeeft die je probleem- of vraagstelling omschrijft.
Zorg in het vervolg dat je een duidelijke titel meegeeft die je probleem- of vraagstelling omschrijft.
Gewijzigd op 30/04/2018 19:07:26 door - Ariën -
ikzelf zou dan denken aan zoiets:
SELECT ID, Title FROM news WHERE ID NOT IN (SELECT news_id FROM gelezen)
Dan kan je kijken of iets in de tabel juist niet voorkomt.
Gewijzigd op 30/04/2018 19:07:56 door - Ariën -
Code (php)
1
2
3
2
3
select ID,Title
from news n
where not exists (select 1 from gelezen where user_id = :user and news_id = n.ID)
from news n
where not exists (select 1 from gelezen where user_id = :user and news_id = n.ID)
"Selecteer alle berichten die nog niet gelezen zijn door deze gebruiker"
En als je de variant van @Ariën gebruikt moet je hier nog even een user toevoegen in de subquery:
Code (php)
1
SELECT ID, Title FROM news WHERE ID NOT IN (SELECT news_id FROM gelezen WHERE User_id = <user id>)
Anders worden alle gelezen berichten (door wie dan ook) er uitgefilterd.
https://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/ zo lees zou de not-exists juist de sloomste van de 3 moeten zijn. Als ik zelf wat testjes doe (MariaDB) merk ik daar weinig van (alle 3 even snel). Zowel de not-exists als not-in komen ook met exact hetzelfde explain plan (met een MATERIALIZED table - die hadden ze in 2009 volgens mij nog niet).
Als ik dit https://dev.mysql.com/doc/refman/8.0/en/subquery-materialization.html zo lees, dan zou de optimizer een not-in sowieso herschrijven naar een not-exists (heuj, not-exists zou dus iets sneller moeten zijn ivm geen rewrite nodig ;-) ), maar door de MATERIALIZED table zijn beide sowieso snel(ler).
Overigens heb ik ook wel eens hele slechte ervaringen met een MATERIALIZED table, waarbij het opbouwen van die temp table veel meer tijd kost dan het doen van een paar lookups voor een exists (grote tabellen met een goede index). De optimizer zover krijgen om niet te materializen is altijd weer gedoe ...
Hm, als ik dit Als ik dit https://dev.mysql.com/doc/refman/8.0/en/subquery-materialization.html zo lees, dan zou de optimizer een not-in sowieso herschrijven naar een not-exists (heuj, not-exists zou dus iets sneller moeten zijn ivm geen rewrite nodig ;-) ), maar door de MATERIALIZED table zijn beide sowieso snel(ler).
Overigens heb ik ook wel eens hele slechte ervaringen met een MATERIALIZED table, waarbij het opbouwen van die temp table veel meer tijd kost dan het doen van een paar lookups voor een exists (grote tabellen met een goede index). De optimizer zover krijgen om niet te materializen is altijd weer gedoe ...
De snelheid is afhankelijk van het aantal records dat doorzocht moet worden. Misschien moet je test set gewoon wat groter? :)
Aan allen hier een dikke merci voor de hulp.
Het is mij gelukt om mijn listing te tonen zoals ik het wilde.
Nogmaals hartelijk bedankt aan de professionals hier.
Ik heb gekozen voor :
SELECT n.ID, n.Title FROM news n
LEFT JOIN gelezen g ON g.user_id = :user AND g.news_id = n.ID
WHERE g.user_id IS NULL
not-exists:
- lokaal 0,110s (DEPENDENT SUBQUERY)
- live 20,8960 (MATERIALIZED)
met een extra "like" om MATERIALIZED te voorkomen (...)
- live 0,0902 (DEPENDENT SUBQUERY)
not-in:
- lokaal 0,094 (DEPENDENT SUBQUERY)
- live 32.4543 (MATERIALIZED)
geen idee hoe ik hier van die MATERIALIZED af kom ...
left-join:
- lokaal 0,094 (2x SIMPLE)
- live 0,0763 (2x SIMPLE)
Dusss, ook met een grote bak data liggen de tijden vrij dicht bij elkaar. Alleen als je de pech hebt dat de "optimizer" tot een MATERIALIZED temp table besluit kun je heel erg nat gaan (uiteraard heeft het soms ook wel voordelen). Kortom: altijd je explain plan checken, en zo af en toe eens in het "Slow Query Log" kijken (of gewoon zelf de duur van een query loggen).
Te vroeg viktorie geroepen ??
Als de gebruiker nog niet in de tabel gelezen staat krijg je een error ?
Met
SELECT n.ID, n.Title FROM news n
LEFT JOIN gelezen g ON g.user_id = :user AND g.news_id = n.ID
WHERE g.user_id IS NULL
Dacht dat het zou lukken maar is niet waar.
Ps de gebruiker komt maar in de tabel "gelezen als hij eentje aanduid dat hij gelezen heeft.
anders moet hij alles zien.
Toevoeging op 01/05/2018 09:48:20:
Hallo,
Heb het zelf opgelost met eerst naar het bestand lezen te gaan kijken en pas deze query uit te voeren als gebruiker er in staat.
Bedankt voor alles.
Knoop berichten en gelezen aan elkaar en toon alles wat niet in gelezen voorkomt door de gebruiker. Lijkt me toch exact te kloppen.
Toch loopt er nog steeds iets mis .
Als ik de listing krijg en ik duid er eentje aan dat gelezen is, komt het in de tabel gelezen, de listing past zich aan
maar het id nr in de listing is verdwenen.
zie hieronder : hier kan je de ID nr nog zien
` a 4 Francis, Still Hobbled, Will Give It Another Try
` a 6 Google Courts Small YouTube Deals, and Very Soon, a Larger
` a 7 A Laptop With Vista That Seems Just Like a Fully Upgraded PC
` a 2 Libya Gingerly Begins Seeking Economic but Not Political Reform
` a 3 Pressed by U.S., Pakistan Seizes a Taliban Chief
` a 9 Opportunists in Somalia 25-4-2007 World news
` a 5 Most Support U.S. Guarantee of Health Care
Ik heb id 2 aangeduid dat het gelezen is en dan krijg ik dit :
` a Francis, Still Hobbled, Will Give It Another Try
` a Google Courts Small YouTube Deals, and Very Soon, a Larger
` a A Laptop With Vista That Seems Just Like a Fully Upgraded PC
` a Pressed by U.S., Pakistan Seizes a Taliban Chief
` a Opportunists in Somalia 25-4-2007 World news
` a Most Support U.S. Guarantee of Health Care
als ik een volgende wil aanduiden kan dit maat hij neemt het ID 2 terug mee terwijl het een ander Id moet zijn.
Kan hier terug even geholpen worden AUB
Dank bij voorbaat.
Toevoeging op 01/05/2018 12:07:53:
Hallo,
bestanden :
newsmain :
id,
Title,
Posted,
Category,
Subcategory,
SmallDescription,
FullDescription
gelezen :
user_id,
news_id
gebruikers :
id,
username,
password,
`Volle naam`,
Category,
Subcatergory
Als ik het volgende uitvoer :
$strSQL = "SELECT n.ID, n.Title, n.Posted, n.Category, n.Subcategory, n.SmallDescription, n.FullDescription FROM newsmain n LEFT JOIN gelezen g ON g.user_id = $sleutel AND g.news_id = n.ID WHERE g.user_id IS NULL ";
doet hij dit maar hij toont n.ID niet meer, blijkbaar zit hij ergens in de knoop ?
hulp AUB
Dank bij voorbaat
Toevoeging op 01/05/2018 13:16:53:
Heb je de query ook al in een mysql console (of desnoods phpmyadmin) gedraaid om te zien of de velden wel zijn zoals je ze verwacht?
Gewijzigd op 01/05/2018 14:18:03 door Ben van Velzen
Als ik dit uitvoer in een mysql console loopt er niks fout.
Ik gebruik phprunner en daarin loopt het fout .
zie hieronder.
Description
Occurs before SQL query executed
Use this event if you like to modify default SQL query on the page.
Avoid editing strSQL parameter, modify strWhereClause and strOrderBy instead.
Parameters
$strSQL - SQL query being to be executed.
$strWhereClause - WHERE clause applied to the SQL query. Example: "active=1"
$strOrderBy - ORDER BY query applied to the SQL query.Example: "ORDER BY
LastName,FirstName"
$pageObject - an object of Page class representing the current page
function BeforeQueryList($strSQL, $strWhereClause, $strOrderBy, $pageObject)
{
$sleutel =$_SESSION["UserID"];
$strSQL = "SELECT n.ID, n.Title, n.Posted, n.Category, n.Subcategory, n.SmallDescription, n.FullDescription FROM newsmain n LEFT JOIN gelezen g ON g.user_id = $sleutel AND g.news_id = n.ID WHERE g.user_id IS NULL ";
Dus, ze geven aan dat je iets niet moet doen en je doet het dan toch? Lijkt me logisch daar dingen mis kunnen gaan. Ik zou zeggen vraag het aan de mensen van phprunner, want hier kan ik uiteraard ook niks mee.
Ik heb het gevonden, maar ik krijg nog een fout.
De fout is nu als er een gebruiker is zoals "FGH123" Krijg ik de foutmelding Unknown column 'FGH123' in 'where clause'
de query = select count(*) FROM `newsmain` where ID NOT IN (SELECT news_id FROM gelezen WHERE user_id = FGH123 )
Als ik een gebruiker maak met alleen cijfers lukt alles.
De velden staan op varchar in beide tabellen.
Weet er iemand raad mee AUB.
Dank U
Er moeten even wat quotes omheen, en vergeet de escaping ook niet. Het is een goede gewoonte om altijd quotes te gebruiken, ook als het om getallen gaat.
Misschien was mijn uitleg niet goed .
Ik gebruik een inlog user als die allemaal cijfers zijn is er geen probleem, als er een letter in staat heb ik een fout.
de query :
SELECT ID, Title FROM news WHERE ID NOT IN (SELECT news_id FROM gelezen WHERE User_id = $sleutel)
$sleutel = de ingelogde user
user_is = varchar
gebruiker of $sleutel = varchar
Hoe kan het dan komen dat cijfers in de query goed zijn en letters niet ?
Bedankt
EDIT: of nog liever, gebruik prepared statements. Scheelt je een hoop kopzorgen en wanneer correct toegepast een lekke applicatie.
Op dit moment is deze query lek, en waarschijnlijk het meerendeel van je andere queries ook. Leuk als je je data wil lekken, minder leuk als anderen in je applicatie komen, om welke reden dan ook.
Gewijzigd op 01/05/2018 22:27:37 door Ben van Velzen