2008-07-03, 13:19
  #1
Medlem
genos avatar
Hej jag har ett problem... jag behöver göra en sqlfråga av det lite mer avancerade slaget (men inte jätteavancerat för det (tror jag)).
Såhär ser mina tre tabeller ut:



CATEGORIES
---------------------
||| id ||| name |||
---------------------

PRODUCTS
----------------------------------
||| id ||| page_id ||| name |||
----------------------------------

PRODUCT CATEGORIES
------------------------------------------
||| id ||| product_id ||| category_id |||
------------------------------------------


Jag ska nu hämta fram produkten på en viss sida (därav page_idt på produkten) och sedan ska jag hämta fram alla kategorier till produkten, och för att slippa imploda och exploda en massa kategorier i ett enda fält i products-tabellen så bestämde jag mig för att skapa "product categories" som ska länka ihop produkterna med kategorierna.
Efter att jag hämta fram rätt produkt till rätt sida med page_id så vill jag att den ska hämta alla kategorier.... och sedan matcha dem med innehållet i "product categories" så att jag med en enkel ifsats kan få ut en kategorilista där jag enkelt och tydligt kan markera vilka categorier som sammankopplats med produkten... den här frågan hittade jag tidigare vilken _nästan_ löste mitt problem, dock så funkar den så att när jag lägger till en kategori till en produkt (lägger till en rad i product categories) så skriver den förvisso ut vilka kategorier som är valda... men den hämtar också ut alla kategorier en gång till så att jag får en massa dubletter:


$query = "SELECT information.category_id, information.id, categories.name, categories.id ".
"FROM categories, information ".
"WHERE information.page_id='".$_GET['page_id']."'";


Någon som kan hjälpa mig med mitt problem?
Citera
2008-07-03, 13:38
  #2
Medlem
Under förutsättningen att en produkt kan höra till flera kategorier skulle jag skrivit tabellen products_categories med endast två främmande nycklar, product_id och category_id.

Queryn kan du enkelt skrivas: "SELECT * FROM categories INNER JOIN product_categories USING (category_id) INNER JOIN products USING (product_id) WHERE products.page_id = 1"
__________________
Senast redigerad av ftcx 2008-07-03 kl. 13:44.
Citera
2008-07-03, 13:43
  #3
Medlem
Glömde en sak...

Om en produkt endast kan höra till en kategori skulle jag lägga category_id som en främmande nyckel i products tabellen, men det kanske du redan har tänkt på?

Ett annat tips är att använda SELECT DISTINCT * FROM tabell för att rensa bort dubletter. Dock är det att föredra att försöka ha en så ren modell från början.

Det är att rekommendera att följa normalformlerna så långt det går http://en.wikipedia.org/wiki/Database_normalization
Citera
2008-07-03, 13:49
  #4
Medlem
genos avatar
Tack för svaren!
Jo det stämmer att en produkt kan höra till flera olika kategorier... och jag har följt normaliseringsstandarderna så långt jag bara kan.
Din fråga ger mig dock ett felmeddelande:

SQL/DB Error -- [Unknown column 'category_id' in 'from clause']

EDIT: Och ja, product_categories innehåller fältet category_id
__________________
Senast redigerad av geno 2008-07-03 kl. 13:53.
Citera
2008-07-03, 15:52
  #5
Medlem
jag brukar ha för vana att sätta samma namn på nycklarna i de tabeller som ska användas. alltså category_id, name i categories istället för bara id. då funkar USING (nyckel). annars kan du skriva "... categories INNER JOIN product_categories ON categories.id = product_categories.category_id ..."
Citera
2008-07-03, 16:16
  #6
Medlem
genos avatar
Aha okej.... jo det fungerade!

fast jag tror du missförstod mig lite... för nu hämtar den bara de kategorier som redan kopplats till en produkt... jag vill att den ska hämta ALLA kategorier varje gång och spotta ut t.e.x [category_id] = '3' i arrayen ifall produkten har ett fält under product_categories kopplat till sig... och [category_id] = ' ' ifall den kategorin inte kopplats till den produkten.
Och sedan köra en simpel ifsats för att avgöra om kategorin är kopplad till produkten eller inte typ:
if ($sql[category_id] > 0)
{
echo '<a href="">KOPPLAD</a>';
}
else
{
echo '<a href="">ej kopplad</a>';
}


såhär ska det se ut på sidan (så man enkelt kan koppla kategorier av och på):

PRODUKTINFO
bla bla bla bla
bla bla bla bla

KATEGORIER SOM DEN HÄR PRODUKTEN HÖR TILL:

action------KOPPLAD
drama------ej kopplad
komedi-----KOPPLAD
fantasy----ej kopplad
sci-fi------ej kopplad
skräck-----ej kopplad
musikal----ej kopplad


och trycker man då på "ej kopplad" så sätter den in den kategorin på produkten (INSERT INTO product_categories SET category_id=X, product_id=X)
...trycker man sen på "KOPPLAD" så kör den en DELETE FROM i product_categories

Det här är alltså adminsidan för produkten och inte end-user som du säkert förstår...
__________________
Senast redigerad av geno 2008-07-03 kl. 16:19.
Citera
2008-07-03, 20:29
  #7
Medlem
ah men då ska du kolla upp LEFT (eller RIGHT) JOINS

SELECT * FROM categories LEFT JOIN product_categories USING (category_id) LEFT JOIN products USING (product_id);

om det inte finns något att joina med (kopplad som du kallar det) kommer de fälten bli null. det kollar du enkelt med en if sats precis som du har skrivit.
Citera
2008-07-05, 16:02
  #8
Medlem
genos avatar
Tack för all hjälp!

Men jag har fortfarande ett problem kvar och det är att när den "joinar" tabellerna så joinar precis alla rader från tabellen... och jag skulle vilja plocka ut specifika fält bara (alltså ställa krav på vilka fält som ska joinas och inte bara joina hela tabellen), pseudokod:


SELECT * FROM blabla JOIN blublu (WHERE blublu.ownerid=$_SESSION['userid']) ON bla=blu

om du förstår hur jag menar?
(tyvärr så funkar ju inte min pseudokod...)
__________________
Senast redigerad av geno 2008-07-05 kl. 16:32.
Citera
2008-07-05, 16:14
  #9
Medlem
Ruskigbusss avatar
Nu kan jag inte MySql utan T-SQL men utgår från att det inte skiljer så våldsamt mycket.

Vad du vill ha är en UNION mellan två listor;
1. Lista över de kategorier som är kopplade till produkten
2. Lista över de kategorier som inte är kopplade till produkten

(Vad pageID har för betydelse förstod jag inte riktigt?)

Alltså:

SELECT categories.id, categories.name, 1 as kopplad
FROM categories
WHERE categories.id IN (
select category_id FROM product_categories
WHERE product_id = XXXX )
UNION
SELECT categories.name, 0 as kopplad
FROM categories
WHERE categories.id NOT IN (
select category_id FROM product_categories
WHERE product_id = XXXX )
ORDER BY categories.id


XXXX är alltså productid som du på något sätt fått tag i.
Jojo, samma subfråga upprepas, men jag antar att du inte har så jäkla många kategorier.
Citera
2008-07-05, 16:31
  #10
Medlem
genos avatar
Haha, kom just på lösningen själv genom att sitta och gissa lite kod...
kom på att det här löser biffen!


SELECT * FROM blabla JOIN blublu ON bla=blu AND (istället för WHERE) blublu.ownerid=$_SESSION['userid']

Och sen kan man fortsätta sådär med fler joins efter varandra...
Tack för allas hjälp i varje fall!
Citera

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in