Har ett litet problem här och vet inte riktigt hur jag skall lösa det på bästa möjliga sätt, jag är inte en klippa på SQL men visst kan jag skriva avancerade saker. Jag har postat om detta flera gånger på forumet, du får se om Pelles sökning är up to date. =) <b>>Om det nu är nödvändigt? Kanske tänker för mycket, och bortser något eller?</b> Kan ju beskriva systemet och dess upplägg idag. Om jag bygger upp SQL-strängen med SQL, dvs en dynamisk sql-sträng då måste jag ju exekvera den via: Okei! :) Vad står tabellen för? Om du använder SQL Server 2005/2008 kan du skriva spliten så här: Har nu kommit fram till detta: Är det en kolumn i databasen som du vill söka i, eller flera olika? Det är 5 kolumner som fritext sökningen görs på, och det är sql server 2000 som databasserver. Nu är den modifierad ytterligare, och jag tycker den verkar funka bara bra förutom när den söker på exakta ord, eller den kanske funkar bra. Söka på en eller flera specifika ord.
Ligger nu med en SP som gör sökningar i multipla tabeller och kolumner. Jag har en avancerad och en enkel sökmetod på ASP sida som anropar då denna SP.
Lösningen jag vill skapa behandlar endast så att säga ett fritext-fält där man nu via att ex skriva in
montering
så hittar den alla poster med montering i. Nu vill man ju givetvis kunna begränsa sökträffarna ytterligare och jag vill kunna hitta samtliga som innehåller ex:
montering AND urologi
Då skall samtliga poster med montering och urologi i sig hittas, sätter jag
montering OR urologi
Så skall samtliga poster med montering eller urologi hittas.
Kan man lösa detta genom att bara använda sig av SPn så att säga, där man skickar in fritext-fältet? Samt har ni några bra exempel på det ??Sv: Söka på en eller flera specifika ord.
Antingen använder man någon färdig tjänst eller så implementerar man det själv.
Sökning sker i två steg; utsökning och rankning, men för vissa modeller slår man ihop dem, eller utför dem i omvänd ordning.
Den enklaste är att låta ranking avgöras från användaren (säg "senast uppdaterad" eller "artikelnummer"), och bara plocka ut alla som är relevanta. Jag tror att det är det du gör, och att det är det du vill göra.
I så fall förespråkar jag dynamiska sql-satser; något i stil med:
1. Sökning av ett ord sker med S("ord"), där t.ex.
S("ord") = SELECT PageID FROM WordCount WHERE Word = "ord"
2. Får du då in en sträng "A AND B" så får du ta snittet av två sökningar:
S("A AND B") = S("A") INTERSECT S("B")
På samma sätt får du
S("A OR B") = S("A") UNION S("B")
Och mer komplicerade uttryck får du göra en liten parser för, t.ex.
S("(A AND B) OR (C AND D)") = (S("A") INTERSECT S("B")) UNION (S("C") INTERSECT S("D"))
Är du med?
Det är möjligt att du kan ta din SP och koppla köra union etc. på den också.Sv:Söka på en eller flera specifika ord.
Att bygga den dynamiska SQL-satsen med ex. ASP eller ASP.NET osv. hade varit enkelt, men i detta fall är jag låst till att bygga den i SQL, vilket jag tycker ökar svårighetsgraden med hänsyn till att kolla upp allt detta med om de har satt in AND eller OR i söksträngen samt att då kunna bygga upp SQL-satsen utifrån det. Om det nu är nödvändigt? Kanske tänker för mycket, och bortser något eller?
I detta fall är dessutom SQL-Servern av modell SQL Server 2000. Visst, jag hade gärna använt en extern tjänst, men i detta fall är det inte möjligt av den orsaken att det är ett intranät som systemet befinner sig.
Då kvarstår att implementera den själv. SPn idag är hyffsat stor, dock egentligen väldigt simpel och ej skriven av mig. Sv: Söka på en eller flera specifika ord.
Såvida inte databasen själv har stöd för det måste du på något sätt hantera det själv.
Att göra det i SQL är ingenting jag skulle rekommendera. Vad är anledningen till att du inte kan göra det i ASP?
Du kanske kan göra något slags mellansteg i ASP som hanterar själva parsingen och som sen går direkt till en sp?
EDIT: Om det bara återstår att göra det i SP så får principen bli något i stil med
DECLARE @Pos INT, @Mx INT
SET @Pos = 0
SET @Mx = Len(input)
WHILE Pos<Mx
BEGIN
IF SUBSTRING(input, pos, 1) = " "
BEGIN
--nytt ord
END
ELSE
IF SUBSTRING(input, pos, 1) = "("
BEGIN
--Ny grupp
END
END
Exakt parsingkod får du komma på eller hitta själv. Det enklaste här är nog att implementera en FSM, men det är förhållandevis mycket jobb.Sv:Söka på en eller flera specifika ord.
Systemet bygger på Microsoft DNA där vi kan dela in det i följande:
1. UI som består av asp 3.0 sidor som gör anrop till komponenter.
2. Komponenterna (ett gäng dll-filer, 4 st för varje tabell) är sådana som vi skapar per automatik utifrån SPna och tabellerna i databasen, komponenterna blir väl i stort sett ett DAL. Som returnerar Recordsets.
3. Databasen med dess tabeller och SPs. Sv: Söka på en eller flera specifika ord.
Exec()
... uuuuuursrrrsh
Sv: Söka på en eller flera specifika ord.
Har skapat färdigt spliten och lägger in sök orden i en variabel tabell nu istället.
DECLARE @delimiter char(1)
DECLARE @pos int
DECLARE @item varchar(100)
DECLARE @query varchar(255)
DECLARE @tmp varchar(255)
DECLARE @Table table (item varchar(200) not null)
SET @delimiter = ' '
SET @query = 'uppvärmning vätesyra' + @delimiter
SET @pos = charindex(@delimiter,@query,1)
IF @pos <> 0
BEGIN
WHILE @pos <> 0
BEGIN
INSERT INTO @Table Select substring(@query,1,@pos - 1)
Set @query = substring(@query, @pos + 1, len(@query))
Set @pos = charindex(@delimiter,@query)
END
END
ELSE
BEGIN
INSERT INTO @Table(item) SELECT @query
END
select * from @Table
Hur skulle man kunna använda sig av denna variabel tabell som innehåller sökorden på ett vettigt sätt.. eller måste man verkligen bygga upp fanskapet med dynamisk sql?
Gaarggggh....
Sv:Söka på en eller flera specifika ord.
Ska alla ord finnas på en sida, eller är en sida ok om ett ord, vilket som helst, finns?
Om du vill ha något mer komplicerat så är det det som är poängen - det enda vettiga sättet att lösa det är med en riktig parsing.
Det blir lite enklare om du väljer att alla ord ska behandlas lika (antingen motsvarande "AND" mellan alla eller motsvarande "OR" mellan alla). Hur sker själva utsökningen idag?Sv:Söka på en eller flera specifika ord.
<code>
DECLARE @Table table (item varchar(200) not null);
DECLARE @str varchar(1000);
DECLARE @x xml;
SET @str = 'uppvärmning vätesyra';
SET @x = '<i>' + REPLACE(@str, ' ', '</i><i>') + '</i>';
INSERT INTO @Table SELECT x.i.value('.', 'varchar(200)') AS item
FROM @x.nodes('//i') x(i);
SELECT * FROM @Table;
</code>
/HåkanSv: Söka på en eller flera specifika ord.
Sökningen behöver bara fungera så att om du anger:
uppvärmning syra
Så skall detta motsvara: uppvärmning AND syra
idag använder den endast: columnN LIKE '%@param%' samt ett x antal: columnN = @param OR columnN = NULL.
Har iofs kommit en bit på vägen och det funkar bra på mina LIKE, men nu är det bara att få in resten av allt. :)Sv:Söka på en eller flera specifika ord.
/HåkanSv: Söka på en eller flera specifika ord.
Har nu fått till ett script, skall dock försöka få till det lite bättre. Sv:Söka på en eller flera specifika ord.
set ANSI_NULLS OFF
set QUOTED_IDENTIFIER OFF
GO
ALTER PROCEDURE [dbo].[XTR_SokForslagsinfo]
(
@Fritext_o varchar(255) = null,
@BesparingFran_o int = null,
@BesparingTill_o int = null,
@BoloningFran_o int = null,
@BeloningTill_o int = null,
@Sifvklass_o int = null,
@ObjektIdavdelning_o int = null,
@Sokunderavdelning_o varchar(20) = null,
@ObjektIdInstans_o int = null,
@DatumFran_o datetime = null,
@DatumTill_o datetime = null,
@AvslutatDatumFran_o datetime = null,
@AvslutatDatumTill_o datetime = null,
@ForslagId_o int = null,
@Forslagsgivare_o int = null,
@PerIdLamnatTill_o int = null,
@PerIdNuvarande_o int = null,
@Forslagsnamn_o varchar(255) = null,
@Forslagsstatus_o varchar(20) = null,
@Sokbeslutsenaste_o varchar(1000) = null,
@MatchType int = 2
)
AS
BEGIN
DECLARE @delimiter char(1)
DECLARE @pos int
DECLARE @item varchar(100)
DECLARE @tmp varchar(255)
DECLARE @Table table (item varchar(200) COLLATE Finnish_Swedish_CI_AS not null)
DECLARE @Wordcount int
SET @delimiter = ' '
SET @Fritext_o = @Fritext_o + @delimiter
SET @pos = charindex(@delimiter,@Fritext_o,1)
IF(@MatchType != 2)
BEGIN
BEGIN
WHILE @pos <> 0
BEGIN
INSERT INTO @Table Select substring(@Fritext_o,1,@pos - 1)
Set @Fritext_o = substring(@Fritext_o, @pos + 1, len(@Fritext_o))
Set @pos = charindex(@delimiter,@Fritext_o)
END
END
END
ELSE
BEGIN
INSERT INTO @Table(item) SELECT @Fritext_o
END
SET @Wordcount = (select count(item) from @Table)
IF EXISTS(SELECT name FROM tempdb..sysobjects WHERE name like '#ObjektTemp')
DROP TABLE [#ObjektTemp]
CREATE TABLE #ObjektTemp (
OBJ_ID int
)
IF ((NOT @ObjektIdavdelning_o=NULL) AND (NOT @Sokunderavdelning_o = null))
INSERT INTO #ObjektTemp EXECUTE _OBS_HamtaAllaObjektIdBarn @ObjektIdavdelning_o, "FV2_LINJEORG"
ELSE IF (NOT @ObjektIdavdelning_o=NULL)
INSERT INTO #ObjektTemp (OBJ_ID ) VALUES(@ObjektIdavdelning_o)
select
fog.FOG_DIARIENUMMER As Diarienummer,
fog.FOG_ID AS Id,
fog.FOG_NAMN AS Namn,
fog.FOG_INLAMNAT_DATUM AS InlamnatDatum,
fts.FTS_NAMN AS Forslagsstatus,
fgg.FGG_ANONYM As Anonym
from
T_PUP_PERSONUPPGIFTER,
T_FOG_FORSLAG fog inner join
(
select ifog.FOG_ID, (Count(*) * 1.0 / @Wordcount) as traffpoang
from T_FOG_FORSLAG ifog
inner join @Table tbl on
(
ifog.FOG_NAMN like '%'+ tbl.item +'%' OR
ifog.FOG_DIARIENUMMER like '%'+ tbl.item +'%' OR
CONVERT(VARCHAR(8000),ifog.FOG_PROBLEMBESKRIVNING) like '%'+ tbl.item +'%' OR
CONVERT(VARCHAR(8000),ifog.FOG_FORSLAG) like '%'+ tbl.item +'%' OR
CONVERT(VARCHAR(8000),ifog.FOG_FORVANTAT_RESULTAT) like '%'+ tbl.item +'%'
-- OR tbl.Item = NULL
) group by ifog.FOG_ID
) a on fog.FOG_ID = a.FOG_ID
inner join
T_FGG_FORSLAGSGIVARE fgg on fgg.FOG_ID = fog.FOG_ID
inner join
T_FTS_FORSLAGSSTATUS fts on fts.FTS_ID = fog.FTS_ID
where
fgg.PER_ID = T_PUP_PERSONUPPGIFTER.PER_ID AND
/* */
(@BesparingFran_o = null OR FOG_BESPARING_ETT_AR >= @BesparingFran_o) AND
(@BesparingTill_o = null OR FOG_BESPARING_ETT_AR <= @BesparingTill_o) AND
(@BoloningFran_o = null OR (
SELECT
MAX(bsd.BSD_BELONING) as beloning
FROM
T_BSD_BESLUTSDATA As bsd,
V_FOG_SENASTEBELONINGSBESLUT as vfog
WHERE
vfog.FOG_ID = fog.FOG_ID AND
bsd.BST_ID = vfog.BST_ID) >= @BoloningFran_o) AND
(@BeloningTill_o = null OR
(
SELECT
MAX(bsd.BSD_BELONING) as beloning
FROM
T_BSD_BESLUTSDATA As bsd,
V_FOG_SENASTEBELONINGSBESLUT as vfog
WHERE
vfog.FOG_ID = fog.FOG_ID AND
bsd.BST_ID = vfog.BST_ID
) <= @BeloningTill_o) AND
(@ObjektIdavdelning_o = null OR T_PUP_PERSONUPPGIFTER.OBJ_ID_ORGANISATIONSTILLHORIGHET IN (SELECT OBJ_ID FROM #ObjektTemp)) AND
(@ObjektIdInstans_o = null OR OBJ_ID_INSTANS_NUVARANDE = @ObjektIdInstans_o) AND
(@DatumFran_o = null OR FOG_INLAMNAT_DATUM >= @DatumFran_o) AND
(@DatumTill_o = null OR datediff(d,FOG_INLAMNAT_DATUM,@DatumTill_o) >= 0) AND
(@AvslutatDatumFran_o = null OR isnull(FOG_AVSLUTAT_DATUM, '1900-01-01') >= @AvslutatDatumFran_o) AND
(@AvslutatDatumTill_o = null OR datediff(d,isnull(FOG_AVSLUTAT_DATUM, '2099-01-01'),@AvslutatDatumTill_o) >= 0) AND
(@ForslagId_o = null OR fog.FOG_DIARIENUMMER = @ForslagId_o) AND
(@Forslagsgivare_o = null OR @Forslagsgivare_o = T_PUP_PERSONUPPGIFTER.PER_ID) AND
(@PerIdLamnatTill_o = null OR @PerIdLamnatTill_o = fog.PER_ID_LAMNAT_TILL) AND
/* nuvarande handläggare måste söka i remisspersonerna om förslaget är på remiss */
--(@PerIdNuvarande_o = null OR @PerIdNuvarande_o = T_FOG_FORSLAG.PER_ID_NUVARANDE) AND
(@PerIdNuvarande_o = null OR @PerIdNuvarande_o
IN(
SELECT
rem.PER_ID
FROM
T_REM_REMISS rem
WHERE
fog.BST_ID_SENASTEBESLUT = rem.BST_ID AND
rem.REM_HAR_SVARAT != 1
UNION SELECT
(
CASE WHEN
(
BST_ID_SENASTEBESLUT NOT IN
(
SELECT
BST_ID
FROM
T_REM_REMISS
WHERE
T_REM_REMISS.FOG_ID = fog.FOG_ID AND
T_REM_REMISS.REM_HAR_SVARAT != 1
)
) THEN
PER_ID_NUVARANDE
END
)
)
)
/*
Ovanstående betyder: @perIdNuvarande IN ( (remissperson i alla remisser till forslagets senaste beslut som inte är besvarade)
UNION
(PER_ID_NUVARANDE i forslaget om det senaste beslutet inte har nån obesvarad remiss)
)
*/ AND
(@Forslagsnamn_o = null OR fog.FOG_NAMN LIKE "%"+ @Forslagsnamn_o+ "%") AND
(@Forslagsstatus_o = null OR fog.FTS_ID = @Forslagsstatus_o OR
(@Forslagsstatus_o ='AVSL_SLUTBET' AND (fog.FTS_ID='AVSLUTAT' OR fog.FTS_ID='FÄRDIGBEHANDLAT'))) AND
(@Sifvklass_o = null OR @Sifvklass_o IN(
SELECT CONVERT(int,CONVERT(varchar(8),OBJ_DATA)) FROM T_OBJ_OBJEKT, T_BST_BESLUT
WHERE
T_OBJ_OBJEKT.OBJ_ID = T_BST_BESLUT.OBJ_ID_SIFV_KLASS AND
fog.FOG_ID = T_BST_BESLUT.FOG_ID AND
OTY_ID = 'FV2_SIFVKLASS' AND
T_BST_BESLUT.BST_ID IN (
SELECT MAX(bst2.BST_ID) FROM T_BST_BESLUT bst2 WHERE T_BST_BESLUT.FOG_ID=bst2.FOG_ID AND bst2.OBJ_ID_SIFV_KLASS<>null)))
AND traffpoang = 1 or @MatchType <> 1
group by
fog.FOG_DIARIENUMMER,
fog.FOG_ID,
fog.FOG_NAMN,
fog.FOG_INLAMNAT_DATUM,
fts.FTS_NAMN,
fgg.FGG_ANONYM,
a.traffpoang
order by
a.traffpoang
END
Detta blev resultatet, det är en förändrad SQL-sats, har inte skrivit allt i den dock.. det funkar bara bra nu så länge "fritexten" inte är tom. Är den tom, ja då brakar helvetet löst. Segar segar segar sig, sen dör den.
Sv:Söka på en eller flera specifika ord.
Har jag ordet "Brödrost i matsalen." så på
Något ord, alla ord hittar den "Brödrost i matsalen." om jag söker på "matsalen", men inte på Exakt, då måste jag skriva: "matsalen.", men "Brödrost i matsalen" hittas givetvis på sökordet "Brödrost" oavsett om jag använder: Något ord, Alla ord eller Exakt sökning.
Summasumarum är ju då att jag måste stripa bort alla lustiga tecken som:
: . , m.fl. som kan tänka sig komma direkt efter ett ord utan mellanrum för att på så sätt kunna ge en träff på "matsalen" vid en exakt sökning om det visar sig att ordet är det sista i meningen och har en punkt efter sig eller mitt i osv.
Vad tror ni?