Точный порядок сортировки записей, найденных в функции разделения IN в SQL Server - PullRequest
0 голосов
/ 10 ноября 2018

Мне нужно вернуть записи, которые я отправляю в хранимую процедуру, в виде строки, разделенной запятыми, например:

@PMID = 29573145,24106086,20513766,24326307

У меня есть хранимая процедура, которая извлекает записи, такие как

SELECT 
    data, 
    PMID  
FROM
    [dbo].[ADMIN_Publication_JSON] 
WHERE 
    PMID IN (SELECT DATA FROM dbo.Split(@PMID, ',')) 

Проблема, с которой я сталкиваюсь, заключается в том, что набор возвращаемых записей является случайным, и мне нужно это точно, потому что мой конечный пользователь может изменить порядок, и записи должны отображаться в том порядке, который изменит порядок в строке запятой. Это возможно или мне нужно полностью изменить способ извлечения данных? Спасибо

Ответы [ 3 ]

0 голосов
/ 11 ноября 2018
Метод

Split не сортирует столбец Data, что означает, что простое соединение с его результатом может помочь.Вам не нужно ROW_NUMBER () или каких-либо усилий по сортировке.Иметь временную таблицу для хранения Split s результата и LEFT JOIN обоих.Это работает для меня.

CREATE TABLE #Input (PMID varchar(10))
INSERT INTO #Input SELECT Data FROM dbo.Split(@PMID, ',')

SELECT 
   jsn.*
FROM 
   #Input spl INNER JOIN ADMIN_Publication_JSON jsn on spl.PMID = jsn.PMID

Вывод: Возвращает набор в порядке, переданном в @PMID

0 голосов
/ 11 ноября 2018

Прошу прощения, но принятый в настоящее время ответ (от саами) неверен.

Проблема с этим ответом состоит в том, что он использует ROW_NUMBER() OVER(ORDER BY (SELECT NULL)), чтобы получить порядок элементов в строке с разделителями-запятыми, но поскольку order by делается на select null, на самом деле происходит то, что row_number назначит числа в произвольном порядке - который может совпадать или не совпадать с порядком строк в исходной строке.
Для получения дополнительной информации, прочитайте Без ремня безопасности Конора Каннингема - Ожидание заказа без ORDER BY.

Если ваш разделенный UDF возвращает таблицу с двумя столбцами, где один содержит подстроку, а другой содержит ее индекс, например, DelimitedSplit8K Джеффа Модена, тогда просто используйте ItemNumber (или эквивалентный) столбец для order by. Если он возвращает только один столбец, содержащий подстроки, вы можете использовать этот приятный трюк, который я узнал из Аарона Бертранда. Решение старых проблем с новыми функциями SQL Server STRING_AGG и STRING_SPLIT - это гарантирует возврат правильных порядок подстрок, если они уникальны.

Простое изменение в ответе Сами даст вам правильные результаты, если подстроки уникальны в строке с разделителями-запятыми - вместо ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) используйте CHARINDEX(',' + Value + ',', ',' + @Ids + ','), которая будет возвращать индекс каждой подстроки внутри запятой с разделителями. строка:

CREATE TABLE T(
  ID INT,
  SomeValue VARCHAR(45)
);

INSERT INTO T VALUES
(1, 'One'),
(2, 'Two'),
(3, 'Three'),
(4, 'Four'),
(5, 'Five');

DECLARE @IDs VARCHAR(200) = '3,5,2';

SELECT T.*
FROM T 
INNER JOIN 
       (SELECT Value,
               CHARINDEX(',' + Value + ',', ',' + @Ids + ',') AS Seq
       FROM dbo.Split(@Ids, ',')
       ) TT
       ON T.ID = TT.Value
ORDER BY TT.Seq;
0 голосов
/ 10 ноября 2018

Вы можете использовать функцию окна как

Select T1.data, 
       T1.PMID  
FROM [dbo].[ADMIN_Publication_JSON] T1 INNER JOIN
     (SELECT Data,
             ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) RN
      FROM dbo.Split(@PMID,',')
     ) T2 ON  T1.PMID = T2.Data 
ORDER BY T2.RN;

Вот небольшой пример:

CREATE TABLE T(
  ID INT,
  SomeValue VARCHAR(45)
);

INSERT INTO T VALUES
(1, 'One'),
(2, 'Two'),
(3, 'Three'),
(4, 'Four'),
(5, 'Five');

DECLARE @IDs VARCHAR(200) = '3,5,2';

SELECT T.*
FROM T INNER JOIN 
       (SELECT Value,
               ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) Seq
       FROM STRING_SPLIT(@Ids, ',') --instead of your function
       ) TT
       ON T.ID = TT.Value
ORDER BY TT.Seq;

Демонстрация в реальном времени

...