16. september 2008 - 23:54Der er
3 kommentarer og 2 løsninger
StoredProcedure, overførelse af tilfældigt antal værdier
Hej fellow SQL'er.
Jeg har for nogen en måske ret kompliceret, der udtager en masse værdier fra flere joined tables. Derfor har jeg oprettet et view som giver et bedre overblik, da den bliver brugt rimelig mange steder.
View navn: vEvents
SQL:-:-: SELECT DISTINCT E.* FROM [vEvents] AS E INNER JOIN Villages V1 ON V1.SID = @SID AND V1.UID = E.FromUID LEFT JOIN Villages V2 ON V2.SID = @SID AND V2.UID = E.ToUID WHERE E.[SID] = @SID AND E.EventTypeID IN (20, 23, 26, 29) AND E.Added = '2008-09-11' AND ( sqrt(square(V1.X - @X) + square(V1.Y - @Y)) < @R OR sqrt(square(ISNULL(V2.X, 9999) - @X) + square(ISNULL(V2.Y, 9999) - @Y)) < @R )
Følgende SQL tager 50 millisek, så performance lader ikke til at være et problem, men hvis man kun søger i en gruppe, vil jeg lave en alm equel ... og ikke en "IN ( 12, 12)" da der er langsom, så jeg har også overvejet en: DECLARE @mytalbe TABLE() Og så join på den, da det lader til at være hurtigere, i hvert fald med en rigtig table på ca. 6 rows ...
Mit problem ... hvordan får jeg overført EventTypeID(der kan være flere) .... infoen kommer fra en hjemmeside hvor brugeren kan markere i nogen checkboxe hvad der skal søges efter ... jeg kan bare ikke lige gennemskue hvordan jeg får overført et: List<byte> array fra min .NET kode.
Jeg bruger LINQ to SQL i .NET
Jeg ved ikke rigtig om der mangler flere informationer, men så sig endelig til.
Jeg har før lavet det ved at kalde sp'en med en streng der ser sådan ud: '10,20,30,40'
Og så har jeg lavet følgende der kan hjælpe mig i sp'en:
--En tabel indeholdende en masse tal. CREATE TABLE Numbers ( Number INT PRIMARY KEY )
--Indsæt tallene 1-10000 i tabellen: DECLARE @i INT SET @i = 0 WHILE @i < 10000 BEGIN INSERT INTO numbers_hend (number) VALUES (@i) SET @i = @i + 1 END
Og så en funktion: /* eksempel på brug: SELECT * FROM fn_split_int_list2table('1,2,3')
giver følgende tabel: -------- |number| -------- | 1 | | 2 | | 3 | -------
Den benytter sig af hjælpe-tabellen: Numbers Kan bruges i en join:
select * from brugere inner join fn_split_int_list2table('1,2,3') users on brugere.id = users.number
*/
CREATE FUNCTION [dbo].[fn_split_int_list2table] ( @ordinal varchar(max) ) RETURNS TABLE AS
RETURN ( SELECT SUBSTRING(@Ordinal+',', number, CHARINDEX(',', @Ordinal+',', number) - number) AS Number FROM Numbers WHERE number <= LEN(@Ordinal) AND SUBSTRING(',' + @Ordinal, number, 1) = ',' )
Pointen er altså, at man bare fodrer sin stored procedure med en kommasepareret liste som en varchar fx, og så bruger man en table valued function til at "konvertere" den til en tabel - som man så kan joine på sine ting. Håber det giver mening, ellers spørg endelig igen.
Du løste faktisk det meste af mit problem, og fik mine tanker i den anden retning efter lidt mere søgning på google. Jeg må sige at jeg kom frem til en lidt flottere løsning synes jeg selv, hvis jeg dog kunne få den sidste lille del til at virke.
declare @string varchar(50) = '10,20,30,40,50,60'; declare @statement nvarchar(100) = 'SELECT EventTypeID FROM EventTypes WHERE EventTypeID IN (' + @string + ')'; exec sp_executesql @statement
Virker super ... men hvordan får jeg mit result sæt smidt i en variable så jeg kan bruge det i min første SQL Query ... :-s ... der er jeg pt låst ... men det kan selvf også ske at det ikke kan lade sig gøre på min måde ...
Smid et svar, du ledte mig på 50% af den rigtige vej.
Endte med at følge rådet om: Process-keyed table ... så må vi se hvordan det går.
indtil videre tager mine 3 quries der skal skydes af ca. 350 ms, hvilket jeg nemt kan leve med når jeg ved hvor meget joins, etc det hele skal igennem. Det hele skydes af gennem et AJAX callback ... så det synes jeg er en fair tid.
Den anden måde med at lave det som dynamisk sql, er også meget brugt, men når man executer denne stump sql, kører det i kontext af sig selv - og dermed kan du ikke rigtig få fat i output'et af det. Tror jeg i hvert fald nok :)
nej, korrekt at man ikke kan få fat i det hvis det er dynamisk SQL ... derfor jeg også endte med process keyed table ... da jeg jo smider mine værdier derover ...:
declare @Statement nvarchar(500) = 'INSERT INTO ProcessKeyed SELECT @@SPID, ET.[Type], ET.EventTypeID FROM EventTypes AS ET LEFT JOIN ProcessKeyed AS PK ON PK.SPID = @@SPID AND ET.EventTypeID = PK.ID WHERE PK.ID IS NULL AND ET.Enable = 1 AND ET.EventTypeID IN ('+ @Input + ')';
Sådan kommer mine værdier over, så er jeg sikker på at jeg ikke får dup keys ...
// ouT
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.