527 messaggi dal 18 dicembre 2012
Ciao a tutti
Spero di essere chiaro.
Vorrei scrivere una query di questo tipo:
SELECT * FROM TbA WHERE ('aa','bb','cc') IN (STRING_SPLIT(Tags, ','))

In pratica: se in Tags è presente o 'aa' o 'bb' o 'cc' deve restiruire la riga nel risultato.

Altro problema: Tags è salvato nel db in questo modo aa,bb,dd,ee,gg,hh
Ci posso essere problemi quando eseguo lo STRING_SPLIT?
Grazie mille
1.976 messaggi dal 27 luglio 2005
Contributi
salve,
Svipla ha scritto:
Ciao a tutti
Spero di essere chiaro.
Vorrei scrivere una query di questo tipo:
SELECT * FROM TbA WHERE ('aa','bb','cc') IN (STRING_SPLIT(Tags, ','))

In pratica: se in Tags è presente o 'aa' o 'bb' o 'cc' deve restiruire la riga nel risultato.

l'unico modo nel linguaggio SQL per un confronto tra insiemi e', come ovviamente sai, un'operazione di JOIN :)

in questo senso puoi quindi "spezzettare" i tags che ti arrivano come parametro e i tag raggruppati nell'attributo di ogni singola riga e quindi effettuare una JOIN che ti restituisca l'insieme derivante...
per "spezzare" i tag puoi ovviamente usare STRING_SPLIT, che io qui di seguito non posso usare che' non ho un SQL Server 2016 sotto mano, ed ho quindi "risolto" con una user defined function con risultato similare, ma tant'e'...

tipicamente, quindi, potrai fare qualche cosa di simile:
SET NOCOUNT ON;
USE tempdb;
GO
CREATE TABLE dbo.t (
  Id int NOT NULL PRIMARY KEY,
  Tags varchar(100)
  );
GO
INSERT INTO dbo.t
  VALUES ( 1, 'aa,bb,cc' ),
    ( 2, 'bb,cc' ),
    ( 3, 'cc' ),
    ( 4, 'aa,dd' ),
    ( 5, 'dd' );
GO
PRINT 'dbo.ufn_Split mi serve in quanto qui non ho SQL Server 2016';
GO
CREATE FUNCTION dbo.ufn_Split (
  @Data varchar(100),
  @sep varchar(1)
  ) 
RETURNS TABLE  
AS  
  RETURN   
  (  
     WITH Pieces(pn, start, stop) AS (
        SELECT 1, 1, CHARINDEX(@sep, @Data)
        UNION ALL
        SELECT pn + 1, stop + 1, CHARINDEX(@sep, @Data, stop + 1)
        FROM Pieces
        WHERE stop > 0
      )
      SELECT pn,
        SUBSTRING(@Data, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
      FROM Pieces
  );  
GO  
PRINT 'Parametro iniziale di confronto';
DECLARE @param varchar(100) = 'aa,bb,cc';
--SET @param = 'dd';

DECLARE @sep varchar(1) = ',';

PRINT 'utilizzo di una CTE per splittare il parametro';
WITH Pieces(pn, start, stop) AS (
      SELECT 1, 1, CHARINDEX(@sep, @param)
      UNION ALL
      SELECT pn + 1, stop + 1, CHARINDEX(@sep, @param, stop + 1)
      FROM Pieces
      WHERE stop > 0
    )
    SELECT pn,
      SUBSTRING(@param, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
    FROM Pieces;

PRINT 'e possiamo avere lo stesso risultato usando dbo.ufn_Split';
SELECT * FROM dbo.ufn_Split(@param, @sep);

PRINT 'tutti i Tags separati di ogni riga';
SELECT t.Id, s.s
  FROM dbo.t t
    CROSS APPLY dbo.ufn_Split(t.Tags, @sep) s;

PRINT 'unisco i pezzi:';
PRINT '1) con cteParam (ma potrei usare SPLIT, ottengo i singoli Tag';
PRINT '2) con cteTabellaTaggata ottengo per ogni riga l''indentificatore di chiave primaria e ogni singo tag';
PRINT '3) con cteDistint prendo un solo Id per ogni riga in un qualche modo taggata,';
PRINT '   ottenuto dal JOIN tra i singoli Tag da parametro e i singoli Tag di ogni riga';
PRINT '4) infine metto in JOIN l''estratto degli Id validi con la tabella originaria';
PRINT '   e proietto il risultato finale';
WITH Pieces(pn, start, stop) AS (
      SELECT 1, 1, CHARINDEX(@sep, @param)
      UNION ALL
      SELECT pn + 1, stop + 1, CHARINDEX(@sep, @param, stop + 1)
      FROM Pieces
      WHERE stop > 0
    ),
cteParam AS (
    SELECT SUBSTRING(@param, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS [Param]
    FROM Pieces
  ),
cteTabellaTaggata AS (
  SELECT t.Id, s.s AS [singleTag]
    FROM dbo.t t
    CROSS APPLY dbo.ufn_Split(t.Tags, @sep) s
  ),
cteDistinct AS (
  SELECT DISTINCT (t.Id)
    FROM cteTabellaTaggata t
      JOIN cteParam p ON p.[Param] = t.[singleTag] 
  )
  SELECT t.*
    FROM dbo.t
      JOIN cteDistinct d ON d.[Id] = t.[Id]
GO
DROP FUNCTION dbo.ufn_Split;
DROP TABLE dbo.t;
--<----------
dbo.ufn_Split mi serve in quanto qui non ho SQL Server 2016
Parametro iniziale di confronto
utilizzo di una CTE per splittare il parametro
pn          s
----------- -----------
1           aa
2           bb
3           cc

e possiamo avere lo stesso risultato usando dbo.ufn_Split
pn          s
----------- -----------
1           aa
2           bb
3           cc

tutti i Tags separati di ogni riga
Id          s
----------- -----------
1           aa
1           bb
1           cc
2           bb
2           cc
3           cc
4           aa
4           dd
5           dd

unisco i pezzi:
1) con cteParam (ma potrei usare SPLIT, ottengo i singoli Tag
2) con cteTabellaTaggata ottengo per ogni riga l'indentificatore di chiave primaria e ogni singo tag
3) con cteDistint prendo un solo Id per ogni riga in un qualche modo taggata,
   ottenuto dal JOIN tra i singoli Tag da parametro e i singoli Tag di ogni riga
4) infine metto in JOIN l'estratto degli Id validi con la tabella originaria
   e proietto il risultato finale
Id          Tags
----------- -----------
1           aa,bb,cc
2           bb,cc
3           cc
4           aa,dd


di nuovo, l'operazione di JOIN permette la definizione di insieme come anche la sua estrusione...

Altro problema: Tags è salvato nel db in questo modo aa,bb,dd,ee,gg,hh
Ci posso essere problemi quando eseguo lo STRING_SPLIT?
Grazie mille


?

salutoni

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php

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.