Avatar billede Syska Mester
16. september 2008 - 23:54 Der 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.

mvh
Avatar billede HenrikSjang Nybegynder
17. september 2008 - 09:00 #1
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.
Avatar billede Syska Mester
17. september 2008 - 10:09 #2
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 ...

// ouT
Avatar billede Syska Mester
17. september 2008 - 14:31 #3
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.

// ouT
Avatar billede HenrikSjang Nybegynder
17. september 2008 - 16:44 #4
Her kommer så et svar :)

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 :)
Avatar billede Syska Mester
17. september 2008 - 21:35 #5
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
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester