Как объединить около одного и того же элемента с помощью SQL? - PullRequest
0 голосов
/ 07 февраля 2012

У меня есть некоторые данные в базе данных:

id user 
1 zhangsan 
2 zhangsan 
3 zhangsan 
4 lisi 
5 lisi 
6 lisi 
7 zhangsan 
8 zhangsan 

Я хочу сохранить порядок и объединить почти одинаковые элементы пользователя, как это сделать? Когда я использую сценарий оболочки, я буду (данные в файле test.):

cat test|cut -d " " -f2|uniq -c 

это получит результат как:

   3 zhangsan 
   3 lisi 
   2 zhangsan 

Но как это сделать, используя sql?

Ответы [ 6 ]

5 голосов
/ 07 февраля 2012

Если вы попытаетесь:

SET @name:='',@num:=0;

SELECT id,
       @num:= if(@name = user, @num, @num + 1) as number,
       @name := user as user
FROM foo
ORDER BY id ASC;

Это даст:

+------+--------+------+
| id   | number | user |
+------+--------+------+
|    1 |      1 | a    |
|    2 |      1 | a    |
|    3 |      1 | a    |
|    4 |      2 | b    |
|    5 |      2 | b    |
|    6 |      2 | b    |
|    7 |      3 | a    |
|    8 |      3 | a    |
+------+--------+------+

Итак, вы можете попробовать:

SET @name:='',@num:=0;

SELECT COUNT(*) as count, user
FROM (
SELECT @num:= if(@name = user, @num, @num + 1) as number,
       @name := user as user
FROM foo
ORDER BY id ASC
) x
GROUP BY number;

Что дает

+-------+------+
| count | user |
+-------+------+
|     3 | a    |
|     3 | b    |
|     2 | a    |
+-------+------+

(я назвал свою таблицу foo, а также просто использовал имена a и b, потому что мне было лень писать zhangsan и lisi снова и снова).

0 голосов
/ 08 февраля 2012

если на сервере sql, oracle, db2 ...

    with x as(  
select c.*, rn = row_number() over (order by c.id)
  from test c 
  left join test n
    on c.[user] = n.[user]
   and c.[id] + 1 = n.[id]   
 where n.id is null
)
select a.[user], a.id - coalesce(b.id, 0) 
  from x a
  left join x b
    on a.rn = b.rn + 1 
0 голосов
/ 07 февраля 2012

если в оракуле, вы можете сделать, как показано ниже.

SELECT NAME,
       num - lagnum
  FROM (SELECT lagname,
               NAME,
               num,
               nvl(lag(num) over(ORDER BY num), 0) lagnum
          FROM (SELECT id,
                       lag(NAME) over(ORDER BY ID) lagname,
                       NAME,
                       lead(NAME) over(ORDER BY ID) leadname,
                       ROWNUM num
                  FROM (SELECT * FROM test ORDER BY ID))
         WHERE (lagname = NAME AND (NAME <> leadname OR leadname IS NULL))
            OR (lagname IS NULL AND NAME <> leadname)
            OR (lagname <> NAME AND leadname IS NULL)
         ORDER BY ID);
0 голосов
/ 07 февраля 2012

Вы не можете сделать это в SQL, не выполняя какой-либо последовательный (итеративный) анализ. Помните, что sql установлен язык операций.

0 голосов
/ 07 февраля 2012

Я думаю, вы ищете COUNT (ID):

SELECT COUNT(ID) FROM table GROUP BY user
0 голосов
/ 07 февраля 2012

Небольшое улучшение в выбранном ответе не должно было бы определять эти переменные. Таким образом, этот запрос может быть решен с помощью одного оператора:

SELECT COUNT(*) cnt, user
FROM (
    SELECT @num := @num + (@name != user) as number,
           @name := user as user
    FROM t, (select @num := 0, @name := '') as s
    ORDER BY id
) x
GROUP BY number

Выход:

| CNT |     USER |
|-----|----------|
|   3 | zhangsan |
|   3 |     lisi |
|   2 | zhangsan |

Скрипка здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...