Query incrociata...
ALonE75
ALonE75 non è online. Ultima attività: 29/05/2006 11.18.53ALonE75
il 26 maggio 2006 alle 16.28
2 messaggi dal 08 ottobre 2005
Ciao a tutti

ho una tabella in cui ho un campo in cui inserisco separati da virgola gli ID di record di un'altra tabella
ora dovrei fare una vista che mi permetta di avere una tabella in cui al posto di tutti gli ID separati da virgola abbia un'unica colonna in cui sono elencati i "valori" corrispondenti di quegli ID

Mi spiego con un esempio
Tabella1
-------------------------------
TAB1_ID | Campo  | TAB2_ID    |
-------------------------------
1          | Valore1  | 1,2   |
2          | Valore2  | 1,3,4 |
3          | Valore3  | 2,4   |
-------------------------------

Tabella2
------------------------------
TAB2_ID | Descrizione        |
------------------------------
1       | Testo1             |
2       | Testo2             |
3       | Testo3             |
4       | Testo4             |
------------------------------

Vista
------------------------------------------------
TAB1_ID | Campo    | Descrizione               |
------------------------------------------------
1       | Valore1  | Testo1,Testo2             |
2       | Valore2  | Testo1,Testo3,Testo4      |
3       | Valore3  | Testo2,Testo4             |
------------------------------------------------



Ho provato a fare delle accrobazie con SQL ma senza risultati...

Un aiutino?

Gracias
Microsoft Most Valuable Professional
Re: Query incrociata...
Andrea Montanari
Andrea Montanari non è online. Ultima attività: 03/07/2009 18.17.01Andrea Montanari Top Poster
il 26 maggio 2006 alle 23.10
Contributi | www.asql.biz | 1.134 messaggi dal 27 luglio 2005
salve,
ALonE75 ha scritto:
Ciao a tutti

ho una tabella in cui ho un campo in cui inserisco separati da virgola gli ID di record di un'altra tabella..


e' una "normalizzazione pessima"  e non ce'e' bisogno che te lo dica.. il disegno architetturale sarebbe sicuramente da ridisegnare, ma tant'e'..


Vista
------------------------------------------------
TAB1_ID | Campo | Descrizione |
------------------------------------------------
1 | Valore1 | Testo1,Testo2 |
2 | Valore2 | Testo1,Testo3,Testo4 |
3 | Valore3 | Testo2,Testo4 |
------------------------------------------------[/code]

Ho provato a fare delle accrobazie con SQL ma senza risultati...
Un aiutino?
Gracias


il motivo e' ppiu' che semplice, (e mi ripeto) la normalizzazione e' piu' che pessima  ...
con SQL Server, tutte le edizioni, con una vista non lo puoi fare, visto che ti devi basare su una "aggregazione di concatenazione" supportata dalle "stringhe", cioe' i tipi di dati char/varchar..
puoi infatti concatenare un risultato intermedio tipo
DECLARE @Result varchar(n);
SET @Result = '';
SELECT @Result = @Result + <colonna> FROM ...

chiaramente devi necessariamente rientrare nel limite del tipo di dato, con SQL Server 2000 ad esempio il limite e' 8000 caratteri per varchar, cosa che potrebbe avere serie problematiche..

di seguito un esempio che utilizza una stored procedure per il ritorno di una unica riga tipo
2 | Valore2 | Testo1,Testo3,Testo4 |
passando come parametro alla stessa il valore della colonna in chiave primaria (nel caso specifico probabilmente Tab1_Id), ed anche un altro esempio che utilizza una funzione definita dall'utente (disponibile solo a partire da SQL Server 2000) basata sullo stesso principio, ma che invece ritorna l'intero set richiesto da proiezione della tabella principale Table1..

mi spiace che il post non manterra' la formattazione del codice, cosa che probabilmente lo rendera' poco leggibile..
a prescindere da cio' il punto fondamentale e' un ciclo appunto su "1,2,n" che prende ogni elemento del multi-attributo e lo utilizza vuoi per un inserimento in una tabella temporanea della quale poi effettuare una JOIN ovvero, nel caso della funzione, di solo caricamento della aggregazione concatenata..

SET NOCOUNT ON;
USE tempdb;
GO
CREATE TABLE dbo.Table1 (
Tab1_ID int NOT NULL ,
Campo varchar(10) NOT NULL, -- Campo?? rotfl
Tab2_ID varchar(50) NOT NULL
);
CREATE TABLE dbo.Table2 (
Tab2_ID int NOT NULL ,
Descrizione varchar(10) NOT NULL
);
GO
INSERT INTO dbo.Table1 VALUES ( 1 , 'Valore 1', '1,2' );
INSERT INTO dbo.Table1 VALUES ( 2 , 'Valore 2', '1,3,4' );
INSERT INTO dbo.Table1 VALUES ( 3 , 'Valore 3', '2,4' );
INSERT INTO dbo.Table1 VALUES ( 4 , 'Valore 4', '' );

INSERT INTO dbo.Table2 VALUES ( 1 , 'Testo 1' );
INSERT INTO dbo.Table2 VALUES ( 2 , 'Testo 2' );
INSERT INTO dbo.Table2 VALUES ( 3 , 'Testo 3' );
INSERT INTO dbo.Table2 VALUES ( 4 , 'Testo 4' );
GO
CREATE PROCEDURE dbo.usp_GetValues (
@Id int
)
AS BEGIN
SET NOCOUNT ON;
CREATE TABLE #temp ( Id int NOT NULL, Tab1_ID int NOT NULL );
DECLARE @Refer varchar(50);
DECLARE @Pos int;
SELECT @Refer = Tab2_ID FROM dbo.Table1 WHERE Tab1_ID = @id;

IF NOT @Refer IS NULL BEGIN
WHILE DATALENGTH(@Refer) <> 0 BEGIN
SELECT @Pos = CHARINDEX(',', @Refer);
IF @Pos <> 0 BEGIN
INSERT INTO #temp VALUES ( CONVERT( int, SUBSTRING (@Refer, 0 , @Pos)), @id );
SET @Refer = SUBSTRING (@Refer, @Pos + 1 , DATALENGTH(@Refer) - @Pos);
END;
ELSE BEGIN
INSERT INTO #temp VALUES (CONVERT( int, @Refer ), @id);
SET @Refer = ''
END;
END;
END;

DECLARE @Result varchar(100);
SET @Result = '';
SELECT @Result = @Result + CASE WHEN DATALENGTH(@Result) <> 0 THEN ', ' ELSE '' END + t2.Descrizione
FROM #temp t
JOIN dbo.Table2 t2 ON t2.Tab2_ID = t.ID;

DROP TABLE #temp;

SELECT t1.Tab1_ID, t1.Campo, @Result AS [Descrizione]
FROM dbo.Table1 t1
WHERE t1.Tab1_ID = @Id;
END;
GO
EXEC dbo.usp_GetValues 1;
EXEC dbo.usp_GetValues 2;
EXEC dbo.usp_GetValues 3;
EXEC dbo.usp_GetValues 4;
GO
CREATE FUNCTION dbo.ufn_GetValues (
@Id int
) RETURNS varchar(100)
AS BEGIN
DECLARE @Refer varchar(50);
DECLARE @Pos int;
SELECT @Refer = Tab2_ID FROM dbo.Table1 WHERE Tab1_ID = @id;

DECLARE @Result varchar(100);
SET @Result = '';
IF NOT @Refer IS NULL BEGIN
WHILE DATALENGTH(@Refer) <> 0 BEGIN
SELECT @Pos = CHARINDEX(',', @Refer);
IF @Pos <> 0 BEGIN
SELECT @Result = @Result + CASE WHEN DATALENGTH(@Result) <> 0 THEN ', ' ELSE '' END + t2.Descrizione
FROM dbo.Table2 t2 WHERE t2.Tab2_ID = CONVERT( int, SUBSTRING (@Refer, 0 , @Pos));

SET @Refer = SUBSTRING (@Refer, @Pos + 1 , DATALENGTH(@Refer) - @Pos);
END;
ELSE BEGIN
SELECT @Result = @Result + CASE WHEN DATALENGTH(@Result) <> 0 THEN ', ' ELSE '' END + t2.Descrizione
FROM dbo.Table2 t2 WHERE t2.Tab2_ID = CONVERT( int, @Refer);
SET @Refer = ''
END;
END;
END;
RETURN (@Result);
END;
GO
SELECT t1.Tab1_ID, t1.Campo, dbo.ufn_GetValues (t1.Tab1_ID) AS [Descrizione]
FROM dbo.Table1 t1;
GO
DROP FUNCTION dbo.ufn_GetValues ;
DROP PROCEDURE dbo.usp_GetValues ;
DROP TABLE dbo.Table2, dbo.Table1 ;

il risultato della chiamata a
EXEC dbo.usp_GetValues n;
e' simile a
Tab1_ID Campo Descrizione
----------- ---------- -----------------
3 Valore 3 Testo 2, Testo 4

dove invece l'utilizzo della funzione ritorna
Tab1_ID Campo Descrizione
----------- ---------- --------------------------
1 Valore 1 Testo 1, Testo 2
2 Valore 2 Testo 1, Testo 3, Testo 4
3 Valore 3 Testo 2, Testo 4
4 Valore 4
a meno di non filtrare
SELECT t1.Tab1_ID, t1.Campo, dbo.ufn_GetValues (t1.Tab1_ID) AS [Descrizione] FROM dbo.Table1 t1 WHERE ......;

cio' non toglie che, ripeto ancora, trattasi di una "normalizzazione pessima"
saluti

Andrea Montanari (Microsoft MVP - SQL Server)
http://www.asql.biz - http://italy.mvps.org
http://www.hotelsole.com - http://www.hotelsolericcione.de
Re: Query incrociata...
ALonE75
ALonE75 non è online. Ultima attività: 29/05/2006 11.18.53ALonE75
il 29 maggio 2006 alle 11.18
2 messaggi dal 08 ottobre 2005
Ciao!

Grazie per la risposta...
Per quanto riguarda la normalizzazione delle tabelle beh... Avrei adottato questa

Tabella1
--------------------
TAB1_ID | Campo    |
--------------------
1       | Valore1  |
2       | Valore2  |
3       | Valore3  |
--------------------

Tabella2
------------------------------
TAB2_ID | Descrizione        |
------------------------------
1       | Testo1             |
2       | Testo2             |
3       | Testo3             |
4       | Testo4             |
------------------------------

TabellaJoin
--------------------------
ID | TAB1_ID | TAB2_ID   |
--------------------------
1  | 1       | 1         |
2  | 1       | 2         |
3  | 2       | 1         |
4  | 2       | 3         |
5  | 2       | 4         |
6  | 3       | 2         |
7  | 3       | 4         |
--------------------------


Che probabilmente è la più corretta (giusto?)
Solo che per vari motivi che non ti sto a elencare (quali l'aver ereditato la situazione così come l'hai vista).
Microsoft Most Valuable Professional
Re: Query incrociata...
Andrea Montanari
Andrea Montanari non è online. Ultima attività: 03/07/2009 18.17.01Andrea Montanari Top Poster
il 29 maggio 2006 alle 17.19
Contributi | www.asql.biz | 1.134 messaggi dal 27 luglio 2005
salve,
ALonE75 ha scritto:
Ciao!

Grazie per la risposta...
Per quanto riguarda la normalizzazione delle tabelle beh... Avrei adottato questa
.....
Che probabilmente è la più corretta (giusto?)



Solo che per vari motivi che non ti sto a elencare (quali l'aver ereditato la situazione così come l'hai vista).


saluti

Andrea Montanari (Microsoft MVP - SQL Server)
http://www.asql.biz - http://italy.mvps.org
http://www.hotelsole.com - http://www.hotelsolericcione.de

Vai a:
Torna al forum |   Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.

COMMUNITY
ULTIMI MESSAGGI
MEDIA
IN EVIDENZA
MISC
Powered by .db Forums "Caesar Reborn" v. 2009.6.9