Query per ottenere prima data dove tutti i codici hanno un record

di il
2 risposte

Query per ottenere prima data dove tutti i codici hanno un record

Vorrei cortesemente un aiuto per costruire una query che mi restituisca la prima data dove tutti i codici che intendo filtrare siano presenti con il proprio record.

Faccio un esempio.
Vorrei sapere, filtrando sul Campo1 per A oppure B oppure C, la prima data comune.

Campo1 - Campo2
A - 20/05/2019
B - 20/05/2019
D - 20/05/2019
----------------------------
A - 21/05/2019
B - 21/05/2019
C - 21/05/2019
D - 21/05/2019
----------------------------
A - 22/05/2019
B - 22/05/2019
C - 22/05/2019
D - 22/05/2019

Vorrei che la query mi restituisse 21/05/2019.
Grazie.

2 Risposte

  • Re: Query per ottenere prima data dove tutti i codici hanno un record

    Salve a tutti,

    considerando il "filtro di ricerca" come una concatenazione di [col1], quindi "A-B-C-????" separati da "-" o altro separatore,' possiamo tokenizzare la "lista" in un insieme di righe da poter utilizzare in JOIN con la tabella principale.
    quindi, raggruppando per data (Col2) il prodotto della JOIN filtriamo il risultato raggruppato' per i soli risultati che referenzino TUTTI i Token ottenuti, e da cio' richiediamo la data minima...
    con le Common Table Expressions possiamo "spezzettare" in forma a noi conveniente le varie sub query che effettuano l'intera operazione ad esempio come di seguito:

    consideriamo l'insieme
    
    INSERT INTO dbo.t
    	VALUES	( 'A', '2019-05-18' ), ( 'A', '2019-05-19' ), ( 'A', '2019-05-20' ), ( 'A', '2019-05-21' ), ( 'A', '2019-05-22' )
    		,	( 'B', '2019-05-19' ), ( 'B', '2019-05-20' ), ( 'B', '2019-05-21' ), ( 'B', '2019-05-22' )
    		,	( 'C', '2019-05-21' ), ( 'C', '2019-05-22' )
    		,	( 'D', '2019-05-20' ), ( 'D', '2019-05-21' ), ( 'D', '2019-05-22' );
    
    dove, come indicato, tokenizziamo il "filtro di ricerca" {concatenazione di [col1], quindi "A-B-C-????" separati da "-" o altro separatore} in un set come
    
    DECLARE @colFilterList varchar(8000) = 'A-B-C';
    
    DECLARE @sep char(1) = '-';
    
    PRINT 'possiamo tokenizzare la "lista" in un insieme di righe da poter utilizzare in JOIN con la tabella principale:';
    WITH Pieces(pn, startPos, endPos, flgList) AS (
    	SELECT 1, 1, CHARINDEX(@sep, @colFilterList), @colFilterList AS flgList
    	UNION ALL
    	SELECT pn + 1, endPos + 1, CHARINDEX(@sep, Pieces.flgList , endPos + 1), Pieces.flgList
    		FROM Pieces		
    		WHERE endPos > 0
    	),
    	cteAllGroups AS (		
    		SELECT LTRIM(RTRIM(SUBSTRING(Pieces.flgList, startPos, CASE WHEN endPos > 0 THEN endPos-startPos ELSE 8000 END))) AS [Col1]
    			FROM Pieces 
    	)
    	SELECT * FROM cteAllGroups;
    
    e quindi, per finire:
    
    PRINT 'quindi, raggruppando per data (Col2) il prodotto della JOIN filtriamo il risultato raggruppato'
    PRINT ' per i soli risultati che referenzino tutti i Token ottenuti quindi:-> HAVING COUNT(*) = (SELECT COUNT(*) FROM cteAllGroups)';
    PRINT ' e quindi richiediamo la data minima del set restituito';
    WITH Pieces(pn, startPos, endPos, flgList) AS (
    	SELECT 1, 1, CHARINDEX(@sep, @colFilterList), @colFilterList AS flgList
    	UNION ALL
    	SELECT pn + 1, endPos + 1, CHARINDEX(@sep, Pieces.flgList , endPos + 1), Pieces.flgList
    		FROM Pieces		
    		WHERE endPos > 0
    	),
    	cteAllGroups AS (		
    		SELECT LTRIM(RTRIM(SUBSTRING(Pieces.flgList, startPos, CASE WHEN endPos > 0 THEN endPos-startPos ELSE 8000 END))) AS [Col1]
    			FROM Pieces 
    	),
    	cteGroupByDate AS (
    		SELECT MIN(t.[col2]) AS [col2]
    			FROM dbo.t t
    				JOIN cteAllGroups c ON t.[col1] = c.[Col1]
    			GROUP BY t.[col2]
    			HAVING COUNT(*) = (SELECT COUNT(*) FROM cteAllGroups)
    	)
    	SELECT MIN(c.[col2]) AS [col2]
    		FROM cteGroupByDate c;
    --<-----------------
    considerando il filtro di ricerca come una concatenazione di [col1], quindi "A-B-C-????" separati da "-" o altro separatore,
    tokenizedFilter
    ----------------
    A-B-C
    
    possiamo tokenizzare la "lista" in un insieme di righe da poter utilizzare in JOIN con la tabella principale:
    Col1
    ----
    A
    B
    C
    
    quindi, raggruppando per data (Col2) il prodotto della JOIN filtriamo il risultato raggruppato
     per i soli risultati che referenzino tutti i Token ottenuti HAVING COUNT(*) = (SELECT COUNT(*) FROM cteAllGroups)
     e quindi richiediamo la data minima del set restituito
    col2
    
    ----------
    2019-05-21
            
    
    saluti omnia
    --
    Andrea
  • Re: Query per ottenere prima data dove tutti i codici hanno un record

    Andrea… che dire.. WOW
Devi accedere o registrarti per scrivere nel forum
2 risposte