FAQ |
Kalender |
![]() |
#1 | ||
|
|||
Medlem
|
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:%' Arbetar med mysql/PHP Tack på förhand! |
||
![]() |
![]() |
![]() |
#2 | ||
|
|||
Administratör
|
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:%')
__________________
eldefors.com - Personlig (teknik)-blogg |
||
![]() |
![]() |
![]() |
#3 | ||
|
|||
Mycket flitig postare
|
Eller ännu bättre är antagligen att ändra databasdesign så du inte sparar flera värden i en kolumn.
|
||
![]() |
![]() |
![]() |
#4 | ||
|
|||
Klarade millennium-buggen
|
Detat verkar funka:
Kod:
SELECT * * * FROM * * * *`event` WHERE * * (egenskaper LIKE '%:4:%') OR * * * * * * * * * * *(egenskaper LIKE '%:5:%') OR * * * * * * * * * * *(tillbehor LIKE '%:3:%') OR * * * * * * * * * * *(tillbehor LIKE '%:14:%') 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. |
||
![]() |
![]() |
![]() |
#5 | |||
|
||||
Supermoderator
|
Citat:
![]() "Learn by doing" och då ligger inte intresset i att lära sig normalformerna i början ![]() |
|||
![]() |
![]() |
![]() |
#6 | ||
|
|||
Klarade millennium-buggen
|
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 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); 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; 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); |
||
![]() |
![]() |
![]() |
#7 | ||
|
|||
Klarade millennium-buggen
|
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). |
||
![]() |
![]() |
![]() |
#8 | ||
|
|||
Klarade millennium-buggen
|
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. |
||
![]() |
![]() |
![]() |
#9 | ||
|
|||
Klarade millennium-buggen
|
Citat:
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. |
||
![]() |
![]() |
![]() |
#10 | ||
|
|||
Nykomling
|
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" ![]() |
||
![]() |
![]() |
Svara |
|
|