salve,
ZyRix1st ha scritto:
Salve a tutti, primo post per me
scenario: ho due tabelle A e B, legate 1 a N sui campi A.id e B.idExt con opzionalità sul lato della tabella B (A può non avere campi correlati in B)
problema: devo visualizzare l'elenco dei dati delle due tabelle, indipendentemente dal fatto che gli elementi di A abbiano effettivamente elementi anche in B, quindi uso il left join. il vero problema è che mi serve solo il primo degli elementi eventualmente presenti in B, mentre il left join mi duplica i dati presi da A per correlarli con ogni riga degli elementi di B per quell'elemento. E mi serve il join perchè devo ordinare il tutto su di un campo presente in B.
se ho ben capito, il tutto non ha molto senso... tu vuoi "ridurre" l'esplosione della join, ma filtrando a "monte" il set restituito (che non conterra' piu' tutte le righe di B), per poi ordinare il tutto relativamente a delle righe che potrebbero anche non essere restituite? se questa e' l'analisi, non sta molto in piedi... come non sta molto in piedi la necessita' di restituire una singola riga per B visto che non definisci un ulteriore criterio di filtro su questa, significando potenzialmente una riga "a caso" in quelle relazionate con una riga specifica in A.. non ne vedo molto il motivo..
puoi pero' fare una subquery (o una vista, o una funzione utente) da aggiungere alla SELECT list per ottenere questo TOP 1, ma in questo caso chiaramente perdi la join e la "possibilita' di ordinare per B.?", che, ripeto, a me pare alquanto strano, irrilevante e non ben congegnato...
non indichi che DBMS tu stia utilizzando, personalmente uso SQL Server..
per quello che vale, di seguito un approccio (concettualmente a mio parere completamente sbagliato) che si basa su una subquery che ritorna 1 unica riga per ogni B relazionato ad A basato su un raggruppamento in funzione della funzione MAX per ogni colonna, quindi il dato e' completamente casuale..
SET NOCOUNT ON;
USE tempdb;
GO
CREATE TABLE dbo.tA (
Id int NOT NULL PRIMARY KEY,
Data varchar(10) NOT NULL
);
CREATE TABLE dbo.tB (
Id int NOT NULL PRIMARY KEY,
IdExt int NULL,
Data varchar(10) NOT NULL
);
INSERT INTO dbo.tA VALUES ( 1, '1 riga' );
INSERT INTO dbo.tA VALUES ( 2, '2 riga' );
INSERT INTO dbo.tA VALUES ( 3, '3 riga' );
INSERT INTO dbo.tB VALUES ( 1, 1, '1 riga 1' );
INSERT INTO dbo.tB VALUES ( 2, 1, '2 riga 1' );
INSERT INTO dbo.tB VALUES ( 3, 2, '1 riga 2' );
INSERT INTO dbo.tB VALUES ( 4, NULL, '1 riga 3' );
GO
PRINT 'JOIN tradizionale';
SELECT tA.Id , tA.Data,
b.Id, b.IdExt, b.Data
FROM dbo.tA tA
LEFT JOIN dbo.tB b ON tA.Id = b.IdExt
ORDER BY tA.Id;
PRINT 'JOIN su una sub query';
SELECT tA.Id , tA.Data,
b.Id, b.IdExt, b.Data
FROM dbo.tA tA
LEFT JOIN (
SELECT MAX(tb.IdExt) AS IdExt, MAX(tB.Id) AS Id, MAX(tB.Data) AS Data
FROM dbo.tB tb JOIN dbo.tA tA2
ON tb.IdExt = tA2.Id
GROUP BY tb.IdExt
) AS b ON tA.Id = b.IdExt
ORDER BY b.Id DESC;
GO
DROP TABLE dbo.tA, dbo.tB;
--<-------------
JOIN tradizionale
Id Data Id IdExt Data
----------- ---------- ----------- ----------- ----------
1 1 riga 1 1 1 riga 1
1 1 riga 2 1 2 riga 1
2 2 riga 3 2 1 riga 2
3 3 riga NULL NULL NULL
JOIN su una sub query
Id Data Id IdExt Data
----------- ---------- ----------- ----------- ----------
2 2 riga 3 2 1 riga 2
1 1 riga 2 1 2 riga 1
3 3 riga NULL NULL NULL
saluti