Kom ihåg mig?
Home Menu

Menu


Knepig mysql-sökquery

 
Ämnesverktyg Visningsalternativ
Oläst 2009-01-11, 15:44 #1
linus1 linus1 är inte uppkopplad
Medlem
 
Reg.datum: Jan 2004
Inlägg: 70
linus1 linus1 är inte uppkopplad
Medlem
 
Reg.datum: Jan 2004
Inlägg: 70
Hej,

Har ett problem som jag inte lyckas lösa med en mysql-sträng.

jag vill göra flera sökningar i samma kolumn.
ex:

Kolumn egenskaper:
Sök 1: ':2:'
Sök 2: ':5:'
Sök 3: ':3:'

Kolumn tillbehor:
Sök 1: ':4:'
Sök 2: ':14:'
Sök 3: ':1:'


Söksträngen måste träffa någon (eller flera) i varje kolumn för att raden ska hämtas..

Uppbyggnaden i kolumnen är tal separerade med ":".
ex:
Egenskaper -> :5:6:3:2:7:

Jag har försökt med div. strängar dock utan resultat. AND , OR slår ut varandra om man sätter se som nedan och där av fungerar det inte

Kod:
SELECT * FROM `event`
where egenskaper LIKE '%:4:%' egenskaper LIKE '%:5:%'
AND
tillbehor LIKE '%:3:%' OR tillbehor LIKE '%:3:%'
Någon som har tips eller vet om det ens är möjligt?
Arbetar med mysql/PHP

Tack på förhand!
linus1 är inte uppkopplad   Svara med citatSvara med citat
Oläst 2009-01-11, 15:47 #2
Clarence Clarence är inte uppkopplad
Administratör
 
Reg.datum: Jan 2003
Inlägg: 1 974
Clarence Clarence är inte uppkopplad
Administratör
 
Reg.datum: Jan 2003
Inlägg: 1 974
Sätt en parentes runt alla OR för samma fält bara:
Kod:
SELECT * FROM `event`
where (egenskaper LIKE '%:4:%' OR egenskaper LIKE '%:5:%')
AND
(tillbehor LIKE '%:3:%' OR tillbehor LIKE '%:3:%')
Clarence är inte uppkopplad   Svara med citatSvara med citat
Oläst 2009-01-11, 15:57 #3
WizKid WizKid är inte uppkopplad
Mycket flitig postare
 
Reg.datum: Apr 2004
Inlägg: 618
WizKid WizKid är inte uppkopplad
Mycket flitig postare
 
Reg.datum: Apr 2004
Inlägg: 618
Eller ännu bättre är antagligen att ändra databasdesign så du inte sparar flera värden i en kolumn.
WizKid är inte uppkopplad   Svara med citatSvara med citat
Oläst 2009-01-11, 22:28 #4
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Detat verkar funka:

Kod:
SELECT * * *
FROM * * * *`event`
WHERE * * (egenskaper LIKE '%:4:%') OR
 * * * * * * * * * * *(egenskaper LIKE '%:5:%') OR
 * * * * * * * * * * *(tillbehor LIKE '%:3:%') OR
 * * * * * * * * * * *(tillbehor LIKE '%:14:%')
men för att vara ärlig så är denna tabell inte ens normaliserad enligt 1:a normalformen!!!

Börja med att göra om databasstrukturen så den uppfller 3:e normalformen.

Dvs du bör ha en tabell med alla "egenskaper" en med alla "tillbehör" och "event" samt en kopplingstabell men jag vet inte hur det övriga datat ser ut så det är svårt att ge en direkt rekommendation på en exakt struktur. Kan du avslöja mer om vilken information tabellerna hanterar.
Conny Westh är inte uppkopplad   Svara med citatSvara med citat
Oläst 2009-01-11, 22:37 #5
FredrikMHs avatar
FredrikMH FredrikMH är inte uppkopplad
Supermoderator
 
Reg.datum: Apr 2004
Inlägg: 1 501
FredrikMH FredrikMH är inte uppkopplad
Supermoderator
FredrikMHs avatar
 
Reg.datum: Apr 2004
Inlägg: 1 501
Citat:
Originally posted by ConnyWesth@Jan 11 2009, 22:28
men för att vara ärlig så är denna tabell inte ens normaliserad enligt 1:a normalformen!!!
Man kan inte börja på topp

"Learn by doing" och då ligger inte intresset i att lära sig normalformerna i början
FredrikMH är inte uppkopplad   Svara med citatSvara med citat
Oläst 2009-01-11, 23:36 #6
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Nåväl då får jag väl lov att lägga fram ett förslag till annan struktur på databasen.

Vi får väl ta det i små steg, så jag drar inget om index och optimering.

Jag har skissat lite snabbt på en lösning som innebär följande tabeller:

event
egenskap
tillbehor
event_egenskap
event_tillbehor

samt några vyer för att förenkla anropen. Ursäkta att nedanstående exempel är för SQL-server men jag hade int emin MySQL uppe just nu, det bör inte vara allt för stora skillnader på den här nivån dock.

Kod för att skapa tabellerna:

Kod:
CREATE TABLE [dbo].[egenskap] (
	[egenskaper_id] [int] NOT NULL ,
	[egenskap] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[event] (
	[event_id] [int] IDENTITY (1, 1) NOT NULL ,
	[egenskaper] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
	[tillbehor] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[event_egenskap] (
	[event_id] [int] NOT NULL ,
	[egenskap_id] [int] NOT NULL 
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[event_tillbehor] (
	[event_id] [int] NOT NULL ,
	[tillbehor_id] [char] (10) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[tillbehor] (
	[tillbehor_id] [int] NOT NULL ,
	[tillbehor] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
) ON [PRIMARY]
GO
Sen lägger vi till primärnycklar:

Kod:
ALTER TABLE [dbo].[egenskap] ADD 
	CONSTRAINT [PK_egenskap] PRIMARY KEY *CLUSTERED 
	(
 *[egenskaper_id]
	) *ON [PRIMARY] 
GO

ALTER TABLE [dbo].[event] ADD 
	CONSTRAINT [PK_event] PRIMARY KEY *CLUSTERED 
	(
 *[event_id]
	) *ON [PRIMARY] 
GO

ALTER TABLE [dbo].[event_egenskap] ADD 
	CONSTRAINT [PK_event_egenskap] PRIMARY KEY *CLUSTERED 
	(
 *[event_id],
 *[egenskap_id]
	) *ON [PRIMARY] 
GO

ALTER TABLE [dbo].[event_tillbehor] ADD 
	CONSTRAINT [PK_event_tillbehor] PRIMARY KEY *CLUSTERED 
	(
 *[event_id],
 *[tillbehor_id]
	) *ON [PRIMARY] 
GO

ALTER TABLE [dbo].[tillbehor] ADD 
	CONSTRAINT [PK_tillbehor] PRIMARY KEY *CLUSTERED 
	(
 *[tillbehor_id]
	) *ON [PRIMARY] 
GO

Sen lägger vi till vyer:

Kod:
SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS ON 
GO

CREATE VIEW vEventEgenskap AS
SELECT e.event_id as event_id, p.egenskaper_id egenskap_id, p.egenskap as egenskap FROM event_egenskap e, egenskap p WHERE e.egenskap_id=p.egenskaper_id

GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS ON 
GO

CREATE VIEW vEventTillbehor AS
SELECT e.event_id as event_id, t.tillbehor_id tillbehor_id, t.tillbehor as tillbehor FROM event_tillbehor e, tillbehor t WHERE e.tillbehor_id=t.tillbehor_id

GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS ON 
GO

CREATE VIEW vEvent AS
SELECT p.event_id as event_id, p.egenskap_id varde_id, p.egenskap as varde FROM vEventEgenskap p
UNION
SELECT t.event_id as event_id, t.tillbehor_id varde_id, t.tillbehor as varde FROM vEventTillbehor t

GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

Fyll tabellerna med värden:


Kod:
--------------------------------------------
-- STEG 2 Populera tabellerna med värden
--------------------------------------------
insert into egenskap(egenskaper_id, egenskap) VALUES (1, 'Färg');
insert into egenskap(egenskaper_id, egenskap) VALUES (2, 'Storlek');
insert into egenskap(egenskaper_id, egenskap) VALUES (3, 'Längd');
insert into egenskap(egenskaper_id, egenskap) VALUES (4, 'Bredd');
insert into egenskap(egenskaper_id, egenskap) VALUES (5, 'Antal');
insert into egenskap(egenskaper_id, egenskap) VALUES (6, 'Ålder');

insert into tillbehor(tillbehor_id, tillbehor) VALUES (1, 'Bilradio');
insert into tillbehor(tillbehor_id, tillbehor) VALUES (2, 'Gaffel');
insert into tillbehor(tillbehor_id, tillbehor) VALUES (3, 'Kniv');
insert into tillbehor(tillbehor_id, tillbehor) VALUES (4, 'Tallrik');
insert into tillbehor(tillbehor_id, tillbehor) VALUES (5, 'Sked');
insert into tillbehor(tillbehor_id, tillbehor) VALUES (6, 'DRicksglas');

insert into event(egenskaper, tillbehor) VALUES ('Exotisk','Gorgonzola');
insert into event(egenskaper, tillbehor) VALUES ('Exotisk','Gorgonzola');
insert into event(egenskaper, tillbehor) VALUES ('Exotisk','Gorgonzola');
insert into event(egenskaper, tillbehor) VALUES ('Exotisk','Gorgonzola');
insert into event(egenskaper, tillbehor) VALUES ('Exotisk','Gorgonzola');


insert into event_tillbehor(event_id, tillbehor_id) VALUES (1,1);
insert into event_tillbehor(event_id, tillbehor_id) VALUES (1,2);
insert into event_tillbehor(event_id, tillbehor_id) VALUES (1,3);
insert into event_tillbehor(event_id, tillbehor_id) VALUES (2,3);
insert into event_tillbehor(event_id, tillbehor_id) VALUES (2,5);
insert into event_tillbehor(event_id, tillbehor_id) VALUES (2,6);

insert into event_egenskap(event_id, egenskap_id) VALUES (1,1);
insert into event_egenskap(event_id, egenskap_id) VALUES (1,2);
insert into event_egenskap(event_id, egenskap_id) VALUES (3,3);
insert into event_egenskap(event_id, egenskap_id) VALUES (2,3);
insert into event_egenskap(event_id, egenskap_id) VALUES (4,5);
insert into event_egenskap(event_id, egenskap_id) VALUES (2,6);
Titta på innehållet i tabellerna, så att vi vet att alla data är korrekt:

Kod:
select * from event;
select * from tillbehor;
select * from egenskap;
select * from event_tillbehor;
select * from event_egenskap;

--------------------------------------------
-- STEG 3 Kontrollera att tabellerna fått rätt värden
--------------------------------------------
SELECT * FROM event_egenskap e, egenskap p WHERE e.egenskap_id=p.egenskaper_id AND event_id=1;
SELECT * FROM event_egenskap e, egenskap p WHERE e.egenskap_id=p.egenskaper_id AND event_id=2;

SELECT * FROM event_tillbehor e, tillbehor t WHERE e.tillbehor_id=t.tillbehor_id AND event_id=1;
SELECT * FROM event_tillbehor e, tillbehor t WHERE e.tillbehor_id=t.tillbehor_id AND event_id=2;
Titta om vi har det vi vill ha:

Kod:
SELECT * FROM vEventEgenskap
Kod:
SELECT * FROM vEventTillbehor

Nu kommer vi fram till den ursprungliga frågeställningen. Den ursprungliga databasen hade inte stöd för denna fråga enligt den tredje normalformen, men denna lösning har det, och det här är ett sätt att lösa problemet på:

Kod:
--------------------------------------------
-- STEG 4 Hur skulle vi nu löst ursprungsfrågan
--------------------------------------------

select * from vEventEgenskap p, vEventTillbehor t WHERE p.egenskap_id IN (1,3,5) OR t.tillbehor_id IN (1,14,7);
Conny Westh är inte uppkopplad   Svara med citatSvara med citat
Oläst 2009-01-12, 00:21 #7
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Innan man kan normalisera så måste alla kolumner i en databasstruktur vara "atomära" dvs varje kolumn i en databasrad innehåller ett värde, exempelvis ett postnummer, ett förnamn eller dyligt.

Jag har sett i vissa databaser dotNetNUKE exempelvis så har man adressen till en person som en kolumn i databasen. Det innebär att värdet inte är atomärt.

Man bör dela upp adressen så man kan hantera gatuadressen, postnr, ort, land var för sig. I mycket välnormaliserade databaser har man dessutom delat upp gatuadressen så man plockat ut gatunummer, trappor m.m. Det är dock ett designbeslut man behöver tänka igenom ordentligt så man kan använda de atomära värdena på ett effektivt sätt i sina applikationer.

Det är viktigt att värdena verkligen är atomära så att man kan lita på datat till 100% när man väl använder det exempelvis vid utskick till 4 Miljoner hushåll, det kostar ju ca 30-40 Mkr att göra såna utskick och då är det viktigt att alla siffror och bokstäver är rätt.

Det kan även uppkomma situationer i framtiden när man vill samköra sitt register för en adresskontroll eller kreditkontroll och då måste man kunna matcha de atomära värdena mot atomära värden i en helt annan databas.

Mankan diskutera var gränsen går när det gller namn men man ska egentligen inte ha behovet av att dela upp ett atomärt värde (egentligen egenskapsbegrepp, inte att förväxla med fritextsökningar av namn).


Här är ett dokument som beskriver normalisering:

http://www.eki.mdh.se/personal/bpn01/under...F03_LDD_2_3.pdf

Normalt är det ganska Ok att jobba med just 3:e normalformen (3NF).
Conny Westh är inte uppkopplad   Svara med citatSvara med citat
Oläst 2009-01-12, 08:45 #8
Magnus_A Magnus_A är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: May 2006
Inlägg: 2 604
Magnus_A Magnus_A är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: May 2006
Inlägg: 2 604
Jag ska inte debattera normalisering, och Connys förslag att normalisera databasen verkar vara väldigt bra ur alla synvinklar, men det finns tillfällen då det är smart att serialisera egenskap:värde-par och lägga dem som text i ett värde i en kolumn.
Behovet kan uppkomma då man har väldigt många aparta värde:egenskapspar som sällan återkommer eller som dynamiskt förändras. Om man dessutom inte behöver söka på dem så kan det vara motiverat att stuva undan dem på detta viset. Behöver man söka på dem eller använda dem i beräkningar så är det definitivt värt att bryta ut dem och lägga dem i egna kolumner eller tabeller. Risken är då att tabellen blir övernormaliserad genom att samma information finns på flera ställen, vilket kräver att man har ordning på varifrån värdena hämtas och vilken information som som ska kopieras varifrån.
Magnus_A är inte uppkopplad   Svara med citatSvara med citat
Oläst 2009-01-12, 09:59 #9
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Citat:
Originally posted by Magnus_A@Jan 12 2009, 08:45
Jag ska inte debattera normalisering, och Connys förslag att normalisera databasen verkar vara väldigt bra ur alla synvinklar, men det finns tillfällen då det är smart att serialisera egenskap:värde-par och lägga dem som text i ett värde i en kolumn.
Behovet kan uppkomma då man har väldigt många aparta värde:egenskapspar som sällan återkommer eller som dynamiskt förändras. Om man dessutom inte behöver söka på dem så kan det vara motiverat att stuva undan dem på detta viset. Behöver man söka på dem eller använda dem i beräkningar så är det definitivt värt att bryta ut dem och lägga dem i egna kolumner eller tabeller. Risken är då att tabellen blir övernormaliserad genom att samma information finns på flera ställen, vilket kräver att man har ordning på varifrån värdena hämtas och vilken information som som ska kopieras varifrån.
Övernormalisering har inget med att samma värde finns på flera ställen.

När man inte har normaliserat korrekt så kan man få risk för redundans (det är när samma värde förekommer på flera ställen i databasen) med uppenbara uppdateringsproblem. Normalisering är den metod man använder just för att undvika redundans i databasen.

Som Magnus skriver så finns det även data som inte behöver bearbetas maskinellt utan enbart är användarinmatad information och som man aldrig behöver bearbeta på ett strukturerat sätt, då och endast då kan man man låta bli att normalisera den informationen, men det är viktigt att man är medveten om detta för det blir ett helsike om det senare visar sig att man behöver bearbeta sån information maskinellt. I de projekt jag arbetat har man oftast normaliserat bort detta problem eftersom det får så stora kostnader att rätta till en slarvigt normaliserad databas i efterhand. Jag har arbetat i projekt där man fått bygga om hela databasen och därmed samtliga applikationer som använder den databasen pga slarvig normalisering (gissa om det blev stora kostnader).

Att designa databaser är ingen trivial fråga utan man måste verkligen ha klart för sig vilka begrepp som är vesäntliga för verksamheten och hur de ska organiseras på ett optimalt sätt, det är därför det är så viktigt att man inte hastar och slarvar just med modellering av begreppen.

Så kontentan är att det sällan eller aldrig är särskilt optimalt eller effektivt att slarva med modellering eller normalisering av databaser, konsekvenserna av slarv kan bli kolossalt kostsamma för ett sånt system.
Conny Westh är inte uppkopplad   Svara med citatSvara med citat
Oläst 2009-01-12, 10:02 #10
tozz tozz är inte uppkopplad
Nykomling
 
Reg.datum: Jul 2008
Inlägg: 25
tozz tozz är inte uppkopplad
Nykomling
 
Reg.datum: Jul 2008
Inlägg: 25
Normaliserade databaser har ju förmågan att bli otroligt långsamma, ifall det är webbapps vi pratar om.
Nu är jag inte emot normalisering (ifall någon trodde det), men efter att ha sett hur de som går "by the books" och normaliserar för normaliseringens skull slår huvudet i väggen när besökarna börjar trilla in så är det värt med en liten varning.

Som en kollega en gång sa "vi började med att lära oss databaser och byggde allting så normaliserat vi kunde, det var väldigt dumt"
tozz är inte uppkopplad   Svara med citatSvara med citat
Svara


Aktiva användare som för närvarande tittar på det här ämnet: 1 (0 medlemmar och 1 gäster)
 

Regler för att posta
Du får inte posta nya ämnen
Du får inte posta svar
Du får inte posta bifogade filer
Du får inte redigera dina inlägg

BB-kod är
Smilies är
[IMG]-kod är
HTML-kod är av

Forumhopp


Alla tider är GMT +2. Klockan är nu 14:30.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson
 
Copyright © 2017