SQL Select GROUP BY 部分字段如果有特殊字符
SQL Select GROUP BY part of field if has a special char
有没有办法对字符串的一部分进行 GROUP BY....
我想创建一个 SQLFIDDLE,但它们似乎必须解决服务器问题,所以我必须在此处使其可见....
这将是数据...
CREATE TABLE tblArticle
(
id int auto_increment primary key,
art_id varchar(20),
art_name varchar(30),
art_color varchar(30),
art_type varchar(5)
);
INSERT INTO tblArticle
(art_id, art_name, art_color, art_type)
VALUES
('12345-1','Textile', 'Black','MAT'),
('12345-2','Textile', 'Red','MAT'),
('12345-3','Textile', 'Green','MAT'),
('12345-4','Textile', 'Blue','MAT'),
('54321-1','Textile', 'Black','MAT'),
('54321-2','Textile', 'Red','MAT'),
('54321-3','Textile', 'Green','MAT'),
('54321-4','Textile', 'Blue','MAT');
所以我得到一些像:
| id | art_id | art_name | art_color | art_type |
----------------------------------------------------------
| 1 | 12345-1 | Textile | Black | MAT |
| 2 | 12345-2 | Textile | Red | MAT |
| 3 | 12345-3 | Textile | Green | MAT |
| 4 | 12345-4 | Textile | Blue | MAT |
| 5 | 54321-1 | Textile | Black | MAT |
| 6 | 54321-2 | Textile | Red | MAT |
| 7 | 54321-3 | Textile | Green | MAT |
| 8 | 54321-4 | Textile | Blue | MAT |
| 9 | 9876543 | Textile | White | MAT |
----------------------------------------------------------
我的select长得像
Select art_id, art_name FROM tblArticle WHERE art_type = 'MAT' GROUP BY art_name
我需要的是 art_id(与 -1 或 -2 等无关紧要)和 art_name 来做进一步的查询。
如您所见,我有 2 个不同的 art_id 组...我想按它们分组。
所以我得到了两个组...12345 和 54321。但是我什至不知道如何开始^^
预期结果:
12345, Textile
54321, Textile
9876543, Textile
我尝试将 art_id 添加到我的分组依据,但效果与不使用分组依据相同 ^^
我该怎么做才能实现这一目标?
已解决:
SELECT DISTINCT @IF( @SCAN( art_id, '-' ) +1,
@LEFT( art_id, @SCAN( art_id, '-')),
art_id) AS art_id, art_name
FROM tblArticle
WHERE art_type LIKE '%MAT%';
在这种情况下,DISTINCT
与 GROUP BY
具有相同的效果。
+1
用于在扫描找不到任何内容时获取 0。如果没有找到,实际上它 returns -1。但是 IF 需要 0(假)或 1+(真)。在我的例子中,拳头永远不会有 -
。
无法使用 GROUP BY,因为它只接受整数或列。
为了分组,您必须指定字符串的哪一位作为分组依据。在这种情况下,它是前 5 个字符,因此您可以使用 LEFT(art_id,5)
。这必须在 SELECT
语句中匹配,因此您需要修改它以读取相同的内容。
我将该列别名为 art_id 否则它将是未知的:
SELECT LEFT(art_id,5) AS art_id, art_name
FROM tblArticle
WHERE art_type = 'MAT'
GROUP BY LEFT(art_id,5), art_name
唯一可能出现问题的是,如果您的 ID 开始超过 5 个字符。在这种情况下,您将需要使用 @FIND
来查找破折号并取其左侧。如果没有破折号,这将崩溃,因为 @FIND
函数 returns -1 如果找不到匹配项,所以我们必须使用 @IF
语句来弥补这一点。
在这种情况下我会写:
SELECT @IF(art_id LIKE '%-%'
,@LEFT(art_id, @FIND('-', art_id, 0) - 1)
,art_id
) AS art_id, art_name
FROM tblArticle
WHERE art_type = 'MAT'
GROUP BY @IF(art_id LIKE '%-%'
,@LEFT(art_id, @FIND('-', art_id, 0) - 1)
,art_id
), art_name
@符号是必须的(至少我是这么认为的,不行就不用),我之前没有用过SQLBase,所以参考下面的官方文档:
你可以试试这个,它会计算出破折号的位置并正确分组
Select case when Instr(art_id, '-') = 0
then art_id
else Left(art_id, Instr(art_id, '-') - 1) end, art_name
FROM tblArticle
WHERE art_type = 'MAT'
GROUP BY case when Instr(art_id, '-') = 0
then art_id
else Left(art_id, Instr(art_id, '-') - 1) end
,art_name
如果您不关心其他列意味着按 select 其他列的随机值进行分组,在这种情况下 art_name
并且它可能是 [= 之一的随机值13=] 你可以使用 as
select
substring_index(art_id,'-',1) as atr_id_val ,
art_name
from tblArticle
where art_type = 'MAT'
group by atr_id_val ;
如果您需要 select 所有列并且需要确保所有列都来自 number-{1 or 2}
的最后一个条目,您可以使用 as
select
t1.id,
substring_index(t1.art_id,'-',1) as art_id,
t1.art_name ,
t1.art_color ,
t1.art_type from tblArticle t1
left join tblArticle t2 on substring_index(t2.art_id,'-',1) = substring_index(t1.art_id,'-',1) and t1.id < t2.id and t1.art_type = 'MAT' where t2.id is null ;
art_id 修剪也需要包含在 select 中,我相信。
Select left( art_id, iif(CHARINDEX('-',art_id) > 0,CHARINDEX('-',art_id)-1, len(art_id) )) art_id, art_name
FROM tblArticle
WHERE art_type = 'MAT'
GROUP BY left ( art_id, iif(CHARINDEX('-',art_id) > 0,CHARINDEX('-',art_id)-1, len(art_id) ))
,art_name
有没有办法对字符串的一部分进行 GROUP BY....
我想创建一个 SQLFIDDLE,但它们似乎必须解决服务器问题,所以我必须在此处使其可见....
这将是数据...
CREATE TABLE tblArticle
(
id int auto_increment primary key,
art_id varchar(20),
art_name varchar(30),
art_color varchar(30),
art_type varchar(5)
);
INSERT INTO tblArticle
(art_id, art_name, art_color, art_type)
VALUES
('12345-1','Textile', 'Black','MAT'),
('12345-2','Textile', 'Red','MAT'),
('12345-3','Textile', 'Green','MAT'),
('12345-4','Textile', 'Blue','MAT'),
('54321-1','Textile', 'Black','MAT'),
('54321-2','Textile', 'Red','MAT'),
('54321-3','Textile', 'Green','MAT'),
('54321-4','Textile', 'Blue','MAT');
所以我得到一些像:
| id | art_id | art_name | art_color | art_type |
----------------------------------------------------------
| 1 | 12345-1 | Textile | Black | MAT |
| 2 | 12345-2 | Textile | Red | MAT |
| 3 | 12345-3 | Textile | Green | MAT |
| 4 | 12345-4 | Textile | Blue | MAT |
| 5 | 54321-1 | Textile | Black | MAT |
| 6 | 54321-2 | Textile | Red | MAT |
| 7 | 54321-3 | Textile | Green | MAT |
| 8 | 54321-4 | Textile | Blue | MAT |
| 9 | 9876543 | Textile | White | MAT |
----------------------------------------------------------
我的select长得像
Select art_id, art_name FROM tblArticle WHERE art_type = 'MAT' GROUP BY art_name
我需要的是 art_id(与 -1 或 -2 等无关紧要)和 art_name 来做进一步的查询。
如您所见,我有 2 个不同的 art_id 组...我想按它们分组。
所以我得到了两个组...12345 和 54321。但是我什至不知道如何开始^^
预期结果:
12345, Textile
54321, Textile
9876543, Textile
我尝试将 art_id 添加到我的分组依据,但效果与不使用分组依据相同 ^^
我该怎么做才能实现这一目标?
已解决:
SELECT DISTINCT @IF( @SCAN( art_id, '-' ) +1,
@LEFT( art_id, @SCAN( art_id, '-')),
art_id) AS art_id, art_name
FROM tblArticle
WHERE art_type LIKE '%MAT%';
在这种情况下,DISTINCT
与 GROUP BY
具有相同的效果。
+1
用于在扫描找不到任何内容时获取 0。如果没有找到,实际上它 returns -1。但是 IF 需要 0(假)或 1+(真)。在我的例子中,拳头永远不会有 -
。
无法使用 GROUP BY,因为它只接受整数或列。
为了分组,您必须指定字符串的哪一位作为分组依据。在这种情况下,它是前 5 个字符,因此您可以使用 LEFT(art_id,5)
。这必须在 SELECT
语句中匹配,因此您需要修改它以读取相同的内容。
我将该列别名为 art_id 否则它将是未知的:
SELECT LEFT(art_id,5) AS art_id, art_name
FROM tblArticle
WHERE art_type = 'MAT'
GROUP BY LEFT(art_id,5), art_name
唯一可能出现问题的是,如果您的 ID 开始超过 5 个字符。在这种情况下,您将需要使用 @FIND
来查找破折号并取其左侧。如果没有破折号,这将崩溃,因为 @FIND
函数 returns -1 如果找不到匹配项,所以我们必须使用 @IF
语句来弥补这一点。
在这种情况下我会写:
SELECT @IF(art_id LIKE '%-%'
,@LEFT(art_id, @FIND('-', art_id, 0) - 1)
,art_id
) AS art_id, art_name
FROM tblArticle
WHERE art_type = 'MAT'
GROUP BY @IF(art_id LIKE '%-%'
,@LEFT(art_id, @FIND('-', art_id, 0) - 1)
,art_id
), art_name
@符号是必须的(至少我是这么认为的,不行就不用),我之前没有用过SQLBase,所以参考下面的官方文档:
你可以试试这个,它会计算出破折号的位置并正确分组
Select case when Instr(art_id, '-') = 0
then art_id
else Left(art_id, Instr(art_id, '-') - 1) end, art_name
FROM tblArticle
WHERE art_type = 'MAT'
GROUP BY case when Instr(art_id, '-') = 0
then art_id
else Left(art_id, Instr(art_id, '-') - 1) end
,art_name
如果您不关心其他列意味着按 select 其他列的随机值进行分组,在这种情况下 art_name
并且它可能是 [= 之一的随机值13=] 你可以使用 as
select
substring_index(art_id,'-',1) as atr_id_val ,
art_name
from tblArticle
where art_type = 'MAT'
group by atr_id_val ;
如果您需要 select 所有列并且需要确保所有列都来自 number-{1 or 2}
的最后一个条目,您可以使用 as
select
t1.id,
substring_index(t1.art_id,'-',1) as art_id,
t1.art_name ,
t1.art_color ,
t1.art_type from tblArticle t1
left join tblArticle t2 on substring_index(t2.art_id,'-',1) = substring_index(t1.art_id,'-',1) and t1.id < t2.id and t1.art_type = 'MAT' where t2.id is null ;
art_id 修剪也需要包含在 select 中,我相信。
Select left( art_id, iif(CHARINDEX('-',art_id) > 0,CHARINDEX('-',art_id)-1, len(art_id) )) art_id, art_name
FROM tblArticle
WHERE art_type = 'MAT'
GROUP BY left ( art_id, iif(CHARINDEX('-',art_id) > 0,CHARINDEX('-',art_id)-1, len(art_id) ))
,art_name