2013-09-09 3 views
2

Как получить предыдущий номер записи в SQL Server?Как получить следующий/предыдущий номер записи?

Таблица данных:

Name | SO No. 
----------------- 
Adrian | SO-00001 
Adrian | SO-00002 
Bianca | SO-00003 
Carrie | SO-00004 
Adrian | SO-00005 
Bianca | SO-00006 
Adrian | SO-00007 

Как я могу получить результат, как показано ниже:

Name | SO No. | Previous SO 
------------------------------- 
Adrian | SO-00005 | SO-00002 
+0

using чисто SQL? –

+0

Жаль, что я новичок. Я использую SQL Server Management Studio и добавляю процедуры хранения. Я не знал, что значит чисто SQL. Извините ..... – Anmi

+0

Понимаю, я понятия не имею, как это сделать, используя только SQL-данные, как получение результатов из 2 строк и объединение частей каждой строки для формирования одной строки, будет интересно узнать, что ответ тоже ... –

ответ

4

Это одна будет работать одинаково во всех основных СУБД (включая SQL Server и MySQL)

ОБНОВЛЕНО на основе ваших комментариев

SELECT name, 
     so_no, 
     (
     SELECT MAX(so_no) 
      FROM table1 
      WHERE so_no < t.so_no 
      AND name = t.name 
     ) prev_so_no 
    FROM table1 t 
WHERE so_no = 'SO-00005' 

SQL Server:

ОБНОВЛЕНО основано на ваших комментариях

SELECT name, 
     MAX(so_no) so_no, 
     CASE WHEN MAX(so_no) = MIN(so_no) 
      THEN NULL 
      ELSE MIN(so_no) 
     END prev_so_no 
    FROM 
(
    SELECT TOP 2 t1.name, t1.so_no 
    FROM table1 t1 JOIN table1 t2 
     ON t1.name = t2.name 
    WHERE t2.so_no = 'SO-00005' 
    AND t1.so_no <= t2.so_no 
    ORDER BY so_no DESC 
) q 
    GROUP BY name 

если вы используете SQL Server 2012, то вы можете также использовать аналитическую функцию LAG

SELECT name, so_no, prev_so_no 
    FROM 
(
    SELECT name, so_no, 
     LAG(so_no, 1, NULL) OVER (ORDER BY so_no) prev_so_no, 
     ROW_NUMBER() OVER (ORDER BY so_no DESC) rnum 
    FROM table1 
    WHERE name = 'Adrian' 
    AND so_no <= 'SO-00005' 
) q 
WHERE rnum = 1 

или

SELECT TOP 1 name, so_no, prev_so_no 
    FROM 
(
    SELECT name, so_no, 
     LAG(so_no, 1, NULL) OVER (ORDER BY so_no) prev_so_no 
    FROM table1 
    WHERE name = 'Adrian' 
    AND so_no <= 'SO-00005' 
) q 
ORDER BY so_no DESC 

MySQL:

SELECT name,  
       MAX(so_no) so_no,  
       CASE WHEN MAX(so_no) = MIN(so_no)  
            THEN NULL 
            ELSE MIN(so_no) 
       END prev_so_no 
  FROM 
(
  SELECT name, so_no 
    FROM table1 
   WHERE name = 'Adrian' 
     AND so_no <= 'SO-00005' 
   ORDER BY so_no DESC 
   LIMIT 2 
) q 
   GROUP BY name 

или

SELECT name, 
     SUBSTRING_INDEX(so_no, ',', 1) so_no, 
     CASE WHEN SUBSTRING_INDEX(SUBSTRING_INDEX(so_no, ',', 2), ',', -1) = SUBSTRING_INDEX(so_no, ',', 1) 
      THEN NULL 
      ELSE SUBSTRING_INDEX(SUBSTRING_INDEX(so_no, ',', 2), ',', -1) 
     END prev_so_no 
    FROM 
(
    SELECT name, GROUP_CONCAT(so_no ORDER BY so_no DESC) so_no 
    FROM table1 
    WHERE name = 'Adrian' 
    AND so_no <= 'SO-00005' 
    GROUP BY name 
) q 

Выход для всех запросов:

 
| NAME | SO_NO | PREV_SO_NO | 
|--------|----------|------------| 
| Adrian | SO-00005 | SO-00002 | 

Вот SQLFiddle демо (SQL Server 2008) ОБНОВЛЕНО
Вот SQLFiddle демо (SQL Server 2012)
Ее e is SQLFiddle demo () MySQL)

+0

Хорошее объяснение! –

+0

Я использую MS SQL Server 2008. Если есть только один главный ключ «SO No.», могу ли я получить тот же результат? Извините за мой плохой английский :( – Anmi

+0

@Amni Я обновил самый верхний пример. Здесь [SQLFiddle] (http://sqlfiddle.com/#!3/45d60/5). Сообщите мне, если он сработает для вас. – peterm

0

Try с offset, этот путь не был настолько чистым, но, возможно, может помочь вам с

SELECT name as "Name", 
(SELECT so_no FROM table WHERE name LIKE '%Adrian%' ORDER BY so_no DESC LIMIT 1) as "SO No.", 
(SELECT so_no FROM table WHERE name LIKE '%Adrian%' ORDER BY so_no DESC OFFSET 1 LIMIT 1) as "Previous SO" 
FROM table 
WHERE name LIKE '%Adrian%' 
LIMIT 1; 

Извините, за плохой запрос, вид новичка также :(

+0

Как изменить код, если главный ключ SO No. вместо имени? На самом деле я использую хрустальный отчет, лучше/возможно получить результат более чем в 1 процедуре магазина? – Anmi

+0

Я вижу, я попытаюсь отредактировать его, используя подзапрос внутри подзапроса, однако вы попробовали решение @peterm? возможно, это может дать вам лучший ответ, пока я пытаюсь его исследовать больше. – ksugiarto

+0

Что касается Crystal Report, то это на 'VB.net'? Фактически, использование более чем 1 SP в порядке, например, вызов другой функции или SP внутри другой функции или SP. это то, что вы имели в виду? – ksugiarto