Ana içeriğe geç
Kesit SQL
Orta · T-SQL (SQL Server)

Listeleri bölmek ve birleştirmek: STRING_SPLIT, STRING_AGG, FOR XML PATH

Virgüllü listeyi satırlara, satırları virgüllü listeye çevirmek.

Uygulamada aç, 3 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

Satırdan listeye: STRING_AGG

SQL Server 2017'den beri birden çok satırı tek metinde birleştirmenin yolu STRING_AGG'dır. Sıra önemliyse WITHIN GROUP (ORDER BY ...) eklenir.

SELECT d.name AS departman,
       STRING_AGG(e.first_name, ', ') WITHIN GROUP (ORDER BY e.first_name) AS calisanlar
FROM departments d
JOIN employees e ON e.dept_id = d.dept_id
GROUP BY d.name;

Eski yöntem: FOR XML PATH

2017 öncesi sürümlerde ve eski kodlarda bu kalıbı çok görürsün. Mantığı adım adım:

  1. İç sorgu, her çalışan adının başına ', ' ekler.
  2. FOR XML PATH('') satırları etiketsiz tek bir metin olarak yan yana yazar.
  3. STUFF(metin, 1, 2, '') baştaki fazla ', ''yi siler.
SELECT d.name AS departman,
       STUFF((SELECT ', ' + e.first_name
              FROM employees e
              WHERE e.dept_id = d.dept_id
              ORDER BY e.first_name
              FOR XML PATH('')), 1, 2, '') AS calisanlar
FROM departments d;
Özel karakterlerFOR XML PATH, & ve < gibi karakterleri XML kodlarına çevirir (&amp;). Bunu önlemek için FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') yazılır.

Listeden satıra: STRING_SPLIT

Uygulamadan “Ankara,İzmir,Bursa” gibi virgüllü bir parametre geldiğinde, STRING_SPLIT (2016+) onu value sütunlu bir tabloya çevirir. SQL Server 2022'de üçüncü argüman 1 verilirse sırayı gösteren ordinal sütunu da gelir.

DECLARE @etiketler NVARCHAR(200) = N'kampanya,yeni,indirimli';

SELECT value AS etiket
FROM STRING_SPLIT(@etiketler, ',');

Parametre listesiyle filtrelemek

DECLARE @kategoriler NVARCHAR(200) = N'Kitap,Spor';

SELECT name, category, price
FROM products
WHERE category IN (SELECT value FROM STRING_SPLIT(@kategoriler, ','));

Sütundaki listeyi açmak: CROSS APPLY

WITH t AS (
    SELECT 1 AS siparis, N'kupon,hediye paketi' AS notlar
    UNION ALL
    SELECT 2, N'hızlı kargo'
)
SELECT t.siparis, s.value AS not_
FROM t
CROSS APPLY STRING_SPLIT(t.notlar, ',') AS s;
Diğer SQL türleriPostgreSQL: string_to_table(metin, ',') veya unnest(string_to_array(...)). MySQL: JSON_TABLE ya da özyinelemeli CTE. Oracle: REGEXP_SUBSTR + CONNECT BY LEVEL. Kalıcı çözüm ise listeyi tek sütunda tutmamak (normalizasyon) ve ayrı bir tabloya yazmaktır.
Alıştırmalara geç (3)