Scheda incrociata: memorizzazione di date diverse (Riunione1, Riunione2, Riunione 3 ecc.) Nella stessa colonna

StackOverflow https://stackoverflow.com/questions/1434717

  •  07-07-2019
  •  | 
  •  

Domanda

Devo tenere traccia di date diverse (dinamiche). Pertanto, per un'attività specifica è possibile tenere traccia del numero X di date (ad esempio la data della riunione DDR1, la data della riunione DDR2, la data di scadenza, ecc.)

La mia strategia era quella di creare una tabella (DateTypeID, DateDescription) che memorizzasse la descrizione di ogni data. Quindi ho potuto creare la tabella principale (ID, TaskDescription, DateTypeID). Quindi tutte le date sarebbero in una colonna e potresti dire cosa rappresenta quella data guardando il TypeID. Il problema è visualizzarlo in una griglia. So che dovrei usare una query a campi incrociati, ma non riesco a farlo funzionare. Ad esempio, utilizzo un'istruzione Case in SQL Server 2000 per ruotare la tabella in modo che ciascun nome di colonna sia il nome del tipo di data. SE abbiamo le seguenti tabelle:

Tabella DateType

DateTypeID | DateDescription

 1           | DDR1
 2           | DDR2
 3           | DueDate


Tabella delle attività

ID | TaskDescription

1 | Create Design
2 | Submit Paperwork


Tabella Tasks_DateType

TasksID | DateTypeID | Data
1       |     1         | 09/09/2009
1       |     2         | 10/10/2009
2       |     1         | 11/11/2009
2       |     3         | 12/12/2009


IL RISULTATO DOVREBBE ESSERE:

Descrizione attività | DDr1 | DDR2 | DueDate

Create Design     |09/09/2009 | 10/10/2009 | null
Submit Paperwork  |11/11/2009 | null       | 12/12/2009

SE qualcuno ha idea di come posso fare per ricercare questo, lo apprezzo. Il motivo per cui lo faccio invece di creare una colonna per ogni data, ha a che fare con la possibilità di consentire all'utente in futuro di aggiungere tutte le date che desidera senza dover aggiungere manualmente colonne alla tabella e modificare il codice HTML. Ciò consente anche un semplice codice per confrontare le date o mostrare le attività imminenti in base al loro tipo (es. "Crea la data DDR1 del disegno sta arrivando") Se qualcuno può indicarmi la giusta direzione, lo apprezzo.

È stato utile?

Soluzione

Ecco una risposta corretta, testata con i tuoi dati. Ho usato solo i primi due tipi di data, ma lo faresti comunque al volo.

Select 
    Tasks.TaskDescription,     
    Min(Case DateType.DateDescription When 'DDR1' Then Tasks_DateType.Date End) As DDR1,     
    Min(Case DateType.DateDescription When 'DDR2' Then Tasks_DateType.Date End) As DDR2
From
    Tasks_DateType
    INNER JOIN Tasks ON Tasks_DateType.TaskID = Tasks.TaskID
    INNER JOIN DateType ON Tasks_DateType.DateTypeID = DateType.DateTypeID
Group By
    Tasks.TaskDescription

Modifica

van ha menzionato che le attività senza date non verranno visualizzate. Questo è corretto. L'uso dei join di sinistra (di nuovo, menzionato da van) e la ristrutturazione della query un po 'restituiranno tutte le attività, anche se al momento non è necessario.

Select 
    Tasks.TaskDescription,     
    Min(Case DateType.DateDescription When 'DDR1' Then Tasks_DateType.Date End) As DDR1,     
    Min(Case DateType.DateDescription When 'DDR2' Then Tasks_DateType.Date End) As DDR2
From
    Tasks   
    LEFT OUTER JOIN Tasks_DateType ON Tasks_DateType.TaskID = Tasks.TaskID
    LEFT OUTER  JOIN DateType ON Tasks_DateType.DateTypeID = DateType.DateTypeID
Group By
    Tasks.TaskDescription

Altri suggerimenti

Se le colonne pivot sono sconosciute (dinamiche), dovrai creare la tua query manualmente in ms-sql 2000 o 2005, cioè senza out senza PIVOT.

Ciò implica l'esecuzione di sql dinamico in una procedura memorizzata (generalmente un no-no) o l'interrogazione di una vista con sql dinamico. Quest'ultimo è l'approccio che generalmente seguo.

Per il pivot, preferisco il metodo Rozenshtein piuttosto che le dichiarazioni di casi, come spiegato qui:

http://www.stephenforte.net /PermaLink.aspx?guid=2b0532fc-4318-4ac0-a405-15d6d813eeb8

Modifica

Puoi anche farlo in linq-to-sql, ma emette un codice abbastanza inefficiente (almeno quando lo vedo attraverso linqpad), quindi non lo consiglio. Se sei ancora curioso, posso pubblicare un esempio di come farlo.

Non ho esperienza personale con l'operatore pivot, potrebbe fornire una soluzione migliore.

Ma ho usato un'istruzione case in passato

SELECT 
    TaskDescription, 
    CASE(DateTypeID = 1, Tasks_DateType.Date) AS DDr1, 
    CASE(DateTypeID = 2, Tasks_DateType.Date) AS DDr2,
    ...
FROM Tasks 
    INNER JOIN Tasks_DateType  ON Tasks.ID = Tasks_DateType.TasksID
    INNER JOIN DateType ON Tasks_DateType.DateTypeID = DateType.DateTypeID
GROUP BY TaskDescription

Funzionerà, ma richiederà di modificare l'SQL ogni volta che vengono aggiunte più descrizioni delle attività, quindi non è l'ideale.

Modifica

Sembra che la parola chiave PIVOT sia stata aggiunta in SqlServer 2005, questo esempio fare una query pivot sia in 2000 & amp; 2005, ma è simile alla mia risposta.

Versione 1: + semplice, deve essere modificato ogni volta che viene aggiunto DateType. Quindi non è eccezionale per una soluzione dinamica:

SELECT      tt.ID,
            tt.TaskDescription,
            td1.Date AS DDR1,
            td2.Date AS DDR2,
            td3.Date AS DueDate
FROM        Tasks tt
LEFT JOIN   Tasks_DateType td1
        ON  td1.TasksID = tt.ID AND td1.DateTypeID = 1
LEFT JOIN   Tasks_DateType td2
        ON  td2.TasksID = tt.ID AND td2.DateTypeID = 2
LEFT JOIN   Tasks_DateType td3
        ON  td3.TasksID = tt.ID AND td3.DateTypeID = 3

Versione-2 : completamente dinamico (con alcune limitazioni, ma possono essere gestiti - basta google per questo):

Creazione dinamica di query pivot. Vedi Tabelle incrociate / tabelle pivot dinamiche : devi creare un SP di UDF e quindi utilizzarlo per più scopi. Questo è il post originale, al quale potresti trovare molti link e miglioramenti.

Versione 3 : lascialo solo per la gestione del codice client . Non progetterei il mio SQL per restituire un insieme dinamico di dati, ma piuttosto gestirlo sul client (livello di presentazione). Non vorrei semplicemente gestire alcune colonne dinamiche che derivano dalla mia query, dove devo indovinare cosa sia esattamente. L'unico motivo per cui utilizzo Versione 2 è quando il risultato viene presentato direttamente come tabella per un report. In tutti gli altri casi per i dati veramente dinamici utilizzo il codice client. Ad esempio: avendo una struttura che hai, come collegherai la logica a quel campo DueDate è obbligatorio - non puoi usare vincoli DB; come assicurerai che DDR1 non sia superiore a DDR2? Se queste non sono colonne separate (statiche) nel database (dove è possibile utilizzare VINCOLI), il codice client è quello che convalida la coerenza dei dati.

Buona fortuna!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top