104 messaggi dal 08 novembre 2001
Ciao
Ho uno scenario di questo tipo

un cliente che gestice degli annunci commerciali ha necessità di tenere un'archivio storico degli annunci. Così ogni annuncio al momento del rinnovo dopo la scandenza viene in pratica duplicato su un nuovo annuncio

L'annuncio nuovo si porta dietro nella colonna ID_rinnovato L'ID dell'annuncio da cui proviene. L'annuncio può essere rinnovato N volte (infinto) quindi uno stesso annuncio di partenza può avere molte copie di se stesso

Ora
Per ragioni che riguardano google e l'indicizzazione ho bisogno di redirigere (tramite 301 procedura già belle che pronta) una eventuale chiamata all'annuncio originario verso l'ultimo della lista

Vorrei trovare quest'ultimo annuncio correlato, o meglio vorrei far trovare da MSSQL, questo annuncio (per ragioni che adesso sono lunghe da spiegare. Vorrei in sostanza evitare da codice asp di looppare e far fare il lavoro a mssql, possibilmente senza stored procedure

Come posso fare?
grazie
Marco
1.976 messaggi dal 27 luglio 2005
Contributi
salve,
puoi per favore formalizzare in maniera semplificata la struttura della tabella?


Per ragioni che riguardano google e l'indicizzazione ho bisogno di redirigere (tramite 301 procedura già belle che pronta) una eventuale chiamata all'annuncio originario verso l'ultimo della lista
Vorrei trovare quest'ultimo annuncio correlato,


avendo un Id particolare vuoi quindi ottenere cosa? il primo che ha generato tutti o l'ultimo che e' stato generato?
saluti

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php
104 messaggi dal 08 novembre 2001
Eccola
ID_annuncio, titolo, testo, scadenza, ID_rinnovato, online, ecc


dove ID_rinnovato è L'ID_annuncio dell'annuncio da cui proviene (se rinnovato), ID_annuncio è chiave auto increment

A me serve trovare l'ultimo annuncio collegato in ordine di tempo con online = true

spero di essermi spiegato
Grazie
Marco
1.976 messaggi dal 27 luglio 2005
Contributi
salve,
non so se ho ben compreso...
SET NOCOUNT ON;
USE tempdb;
GO
CREATE TABLE dbo.t (
  ID_Annuncio int NOT NULL IDENTITY PRIMARY KEY,
  Titolo varchar(10) NOT NULL DEFAULT 'a',
  Testo varchar(10) NOT NULL DEFAULT 't',
  Scadenza date NULL,
  ID_Rinnovato int NULL,
  [OnLine] bit NOT NULL DEFAULT 1,
  );
GO
INSERT INTO dbo.t
  VALUES ('a', 't', '20120101', NULL, 1),
    ('a', 't1', '20120101', 1, 1),
    ('a', 't2', '20120101', 1, 1),
    ('a', 't3', '20120101', 1, 1),
    ('a', 't4', NULL, 1, 0);

INSERT INTO dbo.t
  VALUES ('b', 't', '20120101', NULL, 1),
    ('b', 't2', NULL, 6, 0);

INSERT INTO dbo.t
  VALUES ('c', 't', '20120101', NULL, 1),
    ('c', 't1', '20120101', 8, 1)

INSERT INTO dbo.t
  VALUES ('d', 't', '20120101', NULL, 1);

GO
PRINT 'articolo specifico';
DECLARE @Id int = 1;
WITH cte AS (
  SELECT t.ID_Rinnovato, t.ID_Annuncio,
    ROW_NUMBER() OVER (PARTITION BY t.ID_Rinnovato ORDER BY CASE WHEN t.Scadenza IS NULL THEN '21001231' ELSE t.Scadenza END DESC) AS [r]
    FROM dbo.t t
    WHERE t.ID_Rinnovato IS NOT NULL AND t.OnLine = 1
  )
SELECT t.ID_Annuncio, t.OnLine, t.Scadenza, t.Titolo, t.Testo
  , t2.ID_Annuncio AS [IdProsecuzione], t2.OnLine AS [ProsecuzioneOnLine], t2.Scadenza AS [ScadenzaProsecuzione]
  , t2.Titolo AS [TitoloProsecuzione], t2.Testo AS [TestoProsecuzione]
  FROM dbo.t t
    LEFT JOIN cte c ON c.ID_Rinnovato = t.ID_Annuncio AND c.[r] = 1
    LEFT JOIN dbo.t t2 ON t2.ID_Annuncio = c.ID_Annuncio
  WHERE t.ID_Annuncio = @Id;
GO
PRINT 'tutti gli articoli validi';
WITH cte AS (
  SELECT t.ID_Rinnovato, t.ID_Annuncio,
    ROW_NUMBER() OVER (PARTITION BY t.ID_Rinnovato ORDER BY CASE WHEN t.Scadenza IS NULL THEN '21001231' ELSE t.Scadenza END DESC) AS [r]
    FROM dbo.t t
    WHERE t.ID_Rinnovato IS NOT NULL AND t.OnLine = 1
  )
SELECT t.ID_Annuncio, t.OnLine, t.Scadenza, t.Titolo, t.Testo
  , t2.ID_Annuncio AS [IdProsecuzione], t2.OnLine AS [ProsecuzioneOnLine], t2.Scadenza AS [ScadenzaProsecuzione]
  , t2.Titolo AS [TitoloProsecuzione], t2.Testo AS [TestoProsecuzione]
  FROM dbo.t t
    LEFT JOIN cte c ON c.ID_Rinnovato = t.ID_Annuncio AND c.[r] = 1
    LEFT JOIN dbo.t t2 ON t2.ID_Annuncio = c.ID_Annuncio
  WHERE t.ID_Rinnovato IS NULL;

GO
DROP TABLE dbo.t;


allora, abbiamo una serie di annunci... nel caso l'attributo ID_Rinnovato sia NULL, significa che la riga e' "la riga madre" per l'annuncio stesso... per convenienza indichiamo una data di scadenza che pero' probabilmente puo' anche essere NULL nel caso la scadenza non sia definita...
con la common table expression (cte), per ogni "annuncio madre", ricerchiamo tutti i "figli" e li "numeriamo" (attributo [r]) con la funzione di windowing ROW_NUMBER, ordinando per data di scadenza inversa (e nel caso sia NULL gli attribuiamo una scadenza massima del 31/12/2100)... avendo la numerazione ordinale inversa per ogni "annuncio madre", sappiamo che l'ordinale "1" identifica il piu' lontano, quindi nella proiezione finale possiamo mettere in join l'ID_Annuncio di tale riga con la tabella stessa per ottenere le informazioni relative...

ho utilizzato la join addizionale per evitare di recuperare nella cte tutti gli attributi non basilare (titolo e testo) che sicuramente saranno "corposi" con quindi un elevato ricorso sia di I/O che di memoria occupata, per quindi recuperarli solo nell'estrazione filtrata dell'unico ID maggiore richiesto per ogni articolo...

pero', di nuovo, non so se ho ben compreso :)
saluti
Modificato da Andrea Montanari il 02 agosto 2012 01.43 - dimenticavo il filtro per Online = 1

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php
104 messaggi dal 08 novembre 2001
Ciao
Si si grazie hai capito perfettamente

lo sto testando adattato alla mia tabella
sembra funzionare

Ti ringrazio molto, sei stato gentilissimo

Un saluto
Marco

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.