2013-08-21 15 views
12

ho seguito i dati in mio tavolo:gruppo SQL da una parte della stringa

URL   TIME DATE 
-------------------------------------- 
/x   11  2013-08-01 
/x   11  2013-08-01 
/pl/  11  2013-08-01 
/pl/  11  2013-08-03 
/pl/XXX/ 11  2013-08-01 
/pl/XXX/ 11  2013-08-04 
/pl/XXX/1 11  2013-08-01 
/pl/XXX/2 11  2013-08-01 
/pl/YYY/ 11  2013-08-01 
/pl/YYY/1 11  2013-08-01 
/pl/YYY/2 11  2013-08-04 
/pl/YYY/3 11  2013-08-04 

Esiste un modo per gruppo da URL fino al terzo barra (/) in SQL Server? Purtroppo esiste un record che contiene meno di tre.

+0

Dovresti leggere questa domanda: http://stackoverflow.com/questions/8726111/sql-server-find-nth-occurrence-in-a-string – MarcinJuraszek

+0

Questa è una, due o tre barre: 'pl/XXX '? Chiedo perché potrebbe essere lo stesso percorso di/pl/XXX/'. –

+0

@TimSchmelter tutti i dati iniziano con la barra, quindi non è un problema –

risposta

9

Un trucco per contare il numero di barre in una stringa è:

len(url) - len(replace(url,'/','')) 

È quindi possibile utilizzare charindex tre volte per trovare la posizione della terza barra:

select BeforeThirdSlash 
,  max([date]) 
from (
     select case 
       when len(url) - len(replace(url,'/','')) < 3 then url 
       else substring(url, 1, charindex('/', url, charindex('/', 
         url, charindex('/', url)+1)+1)-1) 
       end as BeforeThirdSlash 
     ,  * 
     from @t 
     ) as SubQueryAlias 
group by 
     BeforeThirdSlash 

Live example at SQL Fiddle.

2

È possibile trovare la posizione di ciascuna posizione di / e ritagliare su MAX(position) - presumendo il terzo / è l'ultimo / come da dati.

DECLARE @tbl TABLE (u VARCHAR(255), t INT, d DATE) 

INSERT INTO @tbl (u, t, d) VALUES 
('/x',   11,  '2013-08-01'), 
('/x',   11,  '2013-08-01'), 
('/pl/',  11,  '2013-08-01'), 
('/pl/',  11,  '2013-08-03'), 
('/pl/XXX/', 11,  '2013-08-01'), 
('/pl/XXX/', 11,  '2013-08-04'), 
('/pl/XXX/1', 11,  '2013-08-01'), 
('/pl/XXX/2', 11,  '2013-08-01'), 
('/pl/YYY/', 11,  '2013-08-01'), 
('/pl/YYY/1', 11,  '2013-08-01'), 
('/pl/YYY/2', 11,  '2013-08-04'), 
('/pl/YYY/3', 11,  '2013-08-04') 

;WITH split AS (
    SELECT u, 1 s, CHARINDEX('/', u) p 
    FROM @tbl 
    UNION ALL 
    SELECT u, p + 1, CHARINDEX('/', u, p + 1) 
    FROM split 
) 

SELECT LEFT(t.u, split.i), MAX(t.t), MAX(t.d) 
FROM @tbl t 
JOIN (
    SELECT u, MAX(p) i 
    FROM split 
    GROUP BY u 
) split ON split.u = t.u 
GROUP BY LEFT(t.u, split.i) 

Con un leggero aggiustamento al CTE è possibile controllare le occorrenze

DECLARE @n INT = 3 -- 'nth occurence' 

;WITH split AS (
    SELECT u, CHARINDEX('/', u) i, 1 r 
    FROM (
     SELECT DISTINCT u 
     FROM @tbl 
    ) t 
    WHERE CHARINDEX('/', u) > 0 
    UNION ALL 
    SELECT u, CHARINDEX('/', u, i + 1), r + 1 
    FROM split 
    WHERE r < @n 
    AND CHARINDEX('/', u, i + 1) > 0 
) 

SELECT LEFT(t.u, split.i) u, MAX(t.t) t , MAX(t.d) d 
FROM @tbl t 
JOIN split ON split.u = t.u 
GROUP BY LEFT(t.u, split.i) 

sql fiddle demo

3

una semplice espressione che consente di afferrare la sottostringa fino al terzo '/' carattere è la seguente:

case 
    when patindex('%/%/%/%', url) = 0 then url 
    else left(url,charindex('/',url,charindex('/',url,charindex('/',url)+1)+1)) 
end 

patindex verifica che vi siano almeno tre barre; lo left estrae la sottostringa fino alla terza inclusa.

Con questa espressione in mano, scrivendo un group by è semplice:

SELECT 
    url3, max(tm), max(dt) 
FROM (
    SELECT 
     CASE 
      WHEN patindex('%/%/%/%', url) = 0 THEN url 
      ELSE left(url,charindex('/',url,charindex('/',url,charindex('/',url)+1)+1)) 
     END AS url3 
    , tm 
    , dt 
    FROM test 
) x 
GROUP BY url3 

Demo on SqlFiddle.