Можно ли сгруппировать по первым символам столбца в SQL?

Итак, у меня есть следующая таблица:

Name    Value
A          10
ABC         5
A           8
ABC         3
AB          2

И я хочу этот результат:

Name    Value
A          28    
AB         10    
ABC         8

Поэтому я хочу группировать не по точному совпадению с именем, а по начальным символам. Является ли это возможным?

Я хотел бы видеть больше данных. Если бы ваши данные имели значение ABD, было бы AB сгруппировано с ABC или ABD?

Tim Biegeleisen 27.11.2022 09:39

Привет, с ними обоими. Тогда группа AB также должна содержать значения ABC и ABD.

Rob Don 27.11.2022 09:51

Пожалуйста, отметьте вашу версию РСУБД

Slava Rozhnev 27.11.2022 10:23

Рекурсивно ли это через строки из 4-n символов, т.е. группировка по первым 3 символам, затем по 4 символам и т. д.?

Stu 27.11.2022 10:35

Всего 3 символа и всегда в алфавитном порядке.

Rob Don 27.11.2022 10:47
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
5
201
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

С SQL Server 2022:

SELECT LEFT("Name", "value") AS STRING, SUM("Value") AS TOTAL
FROM   SoIHaveTheFollowingTable
       CROSS APPLY GENERATE_SERIES(1, CASE WHEN LEN("Name") > 3 THEN 3 ELSE LEN("Name") END)
GROUP  BY LEFT("Name", "value")
ORDER BY STRING;

ПРИМЕЧАНИЕ: с регистрозависимой сортировкой базы данных из-за двух столбцов с именами «Значение» и «значение»... Поскольку вы никогда не должны использовать идентификаторы SQL, которые являются зарезервированными словами (значение, имя, тип, дата...)

Для версии < 2022 сначала используйте рекурсивный запрос, чтобы сгенерировать серию значений int.

Зачем использовать рекурсивный запрос в 2019 году или ранее, а не просто подсчет? Согласно комментариям, в OP есть только строки длиной до 3 символов, поэтому добавление рекурсии было бы значительным накладным расходом для чего-то, что на самом деле в ней не нуждается.

Thom A 27.11.2022 11:05

Кроме того, вместо того, чтобы догадываться, что OP использует сопоставление с учетом регистра (что, я думаю, маловероятно), вам действительно следует использовать псевдонимы и квалифицировать свои столбцы.

Thom A 27.11.2022 11:06

@larnu Потому что Роб Дон не соблюдает правила публикации, не предоставляя DDL таблиц ...

SQLpro 27.11.2022 11:45

Я не уверен, почему отсутствие DDL является причиной для использования более медленного решения или причиной для того, чтобы не квалифицировать ваши объекты, @SQLPro . Как SQL Pro, вы должны знать важность псевдонимов и квалификации.

Thom A 27.11.2022 11:56

@larnu Медленнее? Считаете ли вы, что сортировка BINARIES медленнее? Я постоянно доказываю обратное на своих курсах для профессиональных и инженерных школ...

SQLpro 27.11.2022 12:13

Я знаю, что рекурсия медленнее, чем основанная на наборах @SQLPro .

Thom A 27.11.2022 12:20

Вы можете использовать UNION для каждого количества символов, по которым вы хотите сгруппировать. Что-то вроде этого:

SELECT cat, SUM(val) num FROM (
  SELECT SUBSTRING(Name,1,1) cat, SUM(Value) val FROM table GROUP BY cat
  UNION ALL
  SELECT SUBSTRING(Name,1,2) cat, IF(LENGTH(Name)>1, SUM(Value), 0) val FROM table GROUP BY cat
  UNION ALL
  SELECT SUBSTRING(Name,1,3) cat, IF(LENGTH(Name)>2, SUM(Value), 0) val FROM table GROUP BY cat
) a
GROUP BY cat
ORDER BY cat

IF-оператор длины строки предотвращает включение сумм для строк короче, чем длина, которую вы хотите вычислить.

Результат

+──────+─────+
| cat  | num |
+──────+─────+
| A    | 28  |
| AB   | 10  |
| ABC  | 8   |
+──────+─────+

@Michael_Krikorev По соображениям производительности вы должны использовать UNION ALL вместо UNION.... Голосуйте -1

SQLpro 27.11.2022 12:15

@SQLpro спасибо за отзыв. Результаты должны быть одинаковыми. Я обновил ответ на UNION ALL вместо UNION

Michael Krikorev 27.11.2022 12:19
Ответ принят как подходящий

Запрос различается в зависимости от того, включает ли результат non-existent character data (например, «B» не существует для «BC»).

Если вы используете рекурсивный запрос, результат будет содержать non-existent character data.

WITH cte as (
  SELECT SUBSTRING(Name,1,3) Name, SUM(Value) Value FROM Table1
  GROUP BY SUBSTRING(Name,1,3)
  UNION ALL
  SELECT SUBSTRING(Name,1,LEN(Name)-1), Value FROM cte
  WHERE LEN(Name)>1
)
SELECT Name, SUM(Value) FROM cte
GROUP BY Name
ORDER BY Name

Если вы используете присоединенные подзапросы, результат не будет содержать non-existent character data.

WITH cte as (
  SELECT SUBSTRING(Name,1,3) Name, SUM(Value) Value FROM Table1
  GROUP BY SUBSTRING(Name,1,3)
)
SELECT
  t1.Name,
  SUM(t2.Value)
FROM cte t1 JOIN cte t2
  ON t1.Name=SUBSTRING(t2.Name,1,LEN(t1.Name))
GROUP BY t1.Name
ORDER BY t1.Name

рабочий пример дб

Пример с дополнительными данными: db fiddle

Если Name — это 3 символа, SUBSTRING(Name,1,3) — это просто Name. См. следующее.

рабочий пример дб

Пример с дополнительными данными: db fiddle

в требованиях говорится, что это только для 3 первых символов, а не для всей длины строки... голосование -1

SQLpro 27.11.2022 12:17

ОП подтвердил, что это будет не более 3 символов, @SQLpro.

Thom A 27.11.2022 12:21

@larnu Он подтвердил, что исчисление будет выполняться только для 3 символов, никогда не говорит, что все строки имеют длину 3 символа ... Если он будет соблюдать правила публикации, указав DDL таблицы, мы сможем увидеть, является ли этот столбец это СИМВОЛ(3)...

SQLpro 27.11.2022 12:23

Другие вопросы по теме