djfdx wrote:
Come si evince dalla query, la modellazione è corretta:
ho la tabella delle auto, quella degli optional, e quella delle relazioni optional-auto.
qui non c'e' il ddl ed e' abbastanza "confuso", e questo,
tbl_ExC_Jahr_EquipaggiamentiAuto_3.IDAuto INNER JOIN
tbl_ExC_Jahr_Equipaggiamenti AS
tbl_ExC_Jahr_Equipaggiamenti_1 ON
tbl_ExC_Jahr_EquipaggiamentiAuto_1.IDEquip =
tbl_ExC_Jahr_Equipaggiamenti_1.ID INNER JOIN
tbl_ExC_Jahr_Equipaggiamenti AS
tbl_ExC_Jahr_Equipaggiamenti_2 ON
tbl_ExC_Jahr_EquipaggiamentiAuto_2.IDEquip =
tbl_ExC_Jahr_Equipaggiamenti_2.ID INNER JOIN
tbl_ExC_Jahr_Equipaggiamenti AS
tbl_ExC_Jahr_Equipaggiamenti_3 ON
tbl_ExC_Jahr_EquipaggiamentiAuto_3.IDEquip =
tbl_ExC_Jahr_Equipaggiamenti_3.ID
e' una selfjoin della stessa tabella per 3 volte...
quindi probabilmente non ho affatto capito come effettivamente hai implementato la relazione, ma non mi pare proprio sia simile ad un tradizionale disegno 8:8 (molti a molti)
[ho modificato questo passaggio, che prima era 1:8 (1 a molti) e che ovviamente non quadrava il discorso, essendo errato
... scusate]
CREATE TABLE dbo.auto (
Id int NOT NULL,
Nome varchar(5)
);
CREATE TABLE dbo.optional (
Id int NOT NULL,
Nome varchar(5)
);
CREATE TABLE dbo.optional_auto (
IdAuto int NOT NULL,
IdOptional int NOT NULL
);
ma piu' simile ad un
CREATE TABLE dbo.auto (
Id int NOT NULL,
Nome varchar(5)
);
CREATE TABLE dbo.optional (
Id int NOT NULL,
IdAuto int NOT NULL,
Nome varchar(5)
);
come tu hai indicato in
Auto:
....
....
ID
etc...
Optional
....
....
ID
IDAuto
etc...
che in effetti sarebbe una modellazione 1:8 (1 a molti) e non 8:8 (molti a molti)..
in una modellazione come ho indicato, sarebbe sufficiente raggruppare per auto.id dopo il relativo filtro in OR su (optional_auto.idOptional = @paramX or @paramX IS NULL) e stornare tutte le righe che abbiano un COUNT(*) inferiore al numero di parametri valorizzati, similarmente a SET NOCOUNT ON;
USE tempdb;
GO
CREATE TABLE dbo.auto (
Id int NOT NULL,
Nome varchar(5)
);
CREATE TABLE dbo.optional (
Id int NOT NULL,
Nome varchar(5)
);
CREATE TABLE dbo.optional_auto (
IdAuto int NOT NULL,
IdOptional int NOT NULL
);
GO
INSERT INTO dbo.auto VALUES ( 1, 'fiat' ) ;
INSERT INTO dbo.auto VALUES ( 2, 'alfa' ) ;
INSERT INTO dbo.auto VALUES ( 3, 'opel' ) ;
INSERT INTO dbo.optional VALUES ( 1, 'opt1' ) ;
INSERT INTO dbo.optional VALUES ( 2, 'opt2' ) ;
INSERT INTO dbo.optional VALUES ( 3, 'opt3' ) ;
INSERT INTO dbo.optional VALUES ( 4, 'opt4' ) ;
INSERT INTO dbo.optional VALUES ( 5, 'opt5' ) ;
INSERT INTO dbo.optional VALUES ( 6, 'opt6' ) ;
INSERT INTO dbo.optional_auto VALUES ( 1, 1 ) ;
fiat
INSERT INTO dbo.optional_auto VALUES ( 3, 1 ) ;
opel
INSERT INTO dbo.optional_auto VALUES ( 3, 2 ) ;
opel
INSERT INTO dbo.optional_auto VALUES ( 2, 1 ) ;
alfa
INSERT INTO dbo.optional_auto VALUES ( 2, 2 ) ;
INSERT INTO dbo.optional_auto VALUES ( 2, 3 ) ;
INSERT INTO dbo.optional_auto VALUES ( 2, 4 ) ;
INSERT INTO dbo.optional_auto VALUES ( 2, 5 ) ;
INSERT INTO dbo.optional_auto VALUES ( 2, 6 ) ;
GO
DECLARE @param33 int;
DECLARE @param34 int;
DECLARE @param35 int;
DECLARE @param36 int;
DECLARE @cnt int;
SET @cnt = 0
impostare a NULL i parametri interessanti
per ridurre il filtro di inclusione
SELECT @param33 = 1, @param34 = 2, @param35 = 3, @param36 = 4; IF (@param33 IS NOT NULL) SET @cnt = @cnt + 1;
IF (@param34 IS NOT NULL) SET @cnt = @cnt + 1;
IF (@param35 IS NOT NULL) SET @cnt = @cnt + 1;
IF (@param36 IS NOT NULL) SET @cnt = @cnt + 1;
SELECT a.Id, a.Nome
etc
FROM dbo.auto a
JOIN
(SELECT a.Id
FROM dbo.auto a
JOIN dbo.optional_auto oa ON oa.IdAuto = a.Id
JOIN dbo.optional o ON oa.IdOptional = o.Id
WHERE (o.Id = @param33 OR @param33 IS NULL)
OR (o.Id = @param34 OR @param34 IS NULL)
OR (o.Id = @param35 OR @param35 IS NULL)
OR (o.Id = @param36 OR @param36 IS NULL)
GROUP BY a.Id
HAVING COUNT(*)>= @cnt) q ON q.Id = a.Id
ORDER BY a.Id;
PRINT 'riducibile ulteriormente in';
SELECT a.Id, a.Nome
etc
FROM dbo.auto a
JOIN
(SELECT oa.IdAuto
FROM dbo.optional_auto oa
JOIN dbo.optional o ON oa.IdOptional = o.Id
WHERE (o.Id = @param33 OR @param33 IS NULL)
OR (o.Id = @param34 OR @param34 IS NULL)
OR (o.Id = @param35 OR @param35 IS NULL)
OR (o.Id = @param36 OR @param36 IS NULL)
GROUP BY oa.IdAuto
HAVING COUNT(*)>= @cnt) q ON q.IdAuto = a.Id
ORDER BY a.Id;
GO
DROP TABLE dbo.auto, dbo.optional, dbo.optional_auto;
--<------
Id Nome
---------
-----
2 alfa
riducibile ulteriormente in
Id Nome
---------
-----
2 alfa
i singoli parametri vengono quindi valutati tutti in OR l'uno con l'altro, in modo da restituire tutte le righe che abbiano almeno un riscontro nell'insieme di parametri e, per ogni parametro, viene valutato che l'optional sia uguale allo stesso ovvero il parametro sia NULL, nel caso che venga specificato 1 solo parametro (@param33 e basta, e quindi @param34, @param35 e @param36 siano NULLi).. da questa estrusione raggruppata per auto.id vengono scartati i risultati che abbiano un numero di riscontro inferiore al numero di parametri valorizzati..
questo utilizzo l'ho personalmente basato su un attributo di tipo numerico (Id, IdOptional, IdAuto, etc), ma e' corretto anche per altri tipi di dato...
tu utilizzi un LIKE.. che sottintende un attributo di tipo stringa, e questo attributo e' addirittura una chiave, probabilmente primaria, oltre che poi costituire una chiave di integrita' referenziale... questa modellazione, se l'ho ben intesa, non mi piace affatto, ma non deve piacere a me.. al di la' di cio', il LIKE [colonna] = '%' ovviamente e' vero per ogni occorrenza di [colonna] che non sia NULL, quindi ritorna il risultato che segue
SET NOCOUNT ON;
USE tempdb;
GO
CREATE TABLE dbo.t (
id varchar(5) NULL,
val varchar(5)
);
GO
INSERT INTO dbo.t VALUES (NULL, 'NULL');
INSERT INTO dbo.t VALUES ('', 'vuoto');
INSERT INTO dbo.t VALUES ('a', 'a');
INSERT INTO dbo.t VALUES ('1', '1' );
INSERT INTO dbo.t VALUES ('999', '999');
GO
SELECT * FROM dbo.t WHERE Id LIKE '%';
GO
DROP TABLE dbo.t;
--<-----
id val
---
-----
vuoto
a a
1 1
999 999
e non e' affatto cosi' che si costruiscono filtri dinamici, come puoi ovviamente riscontrare da te stesso..
oppure, ripeto ancora e cosa moltro probabile, non ho affatto capito ne' la modellazione ne' quello che stai cercando di ottenere..
saluti
Modificato da Andrea Montanari il 04 settembre 2008 00.53 -