对不起,如果标题令人困惑,这就是我想要做的事情:
INSERT INTO table (fruit, type) VALUES
('apple', '1'),
('apple', '2'),
('apple', '2'),
('banana', '3'),
('banana', '4'),
('banana', '5');
因此,结果表只有两行,type
列中的管道分隔值如下所示:
('apple', '1|2')
('banana', '3|4|5')
现在我有:
CREATE TABLE IF NOT EXISTS table (
id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
fruit varchar(50) NOT NULL UNIQUE KEY,
type varchar(100) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=latin1;
INSERT INTO table (fruit, type) VALUES
('apple', '1'),
('apple', '2'),
('apple', '2'),
('banana', '3'),
('banana', '4'),
('banana', '5')
ON KEY DUPLICATE type = VALUES(type)|type
//I know above line is wrong and this is where I'm stuck
我可以在type
列中获得一系列以管道分隔的值吗?
非常感谢
修改
通过这样做,我几乎得到了最终的结果:
CREATE TABLE IF NOT EXISTS table (
id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
fruit varchar(50) NOT NULL UNIQUE KEY,
type varchar(100) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=latin1;
INSERT INTO table (fruit, type) VALUES
('apple', '1'),
('apple', '2'),
('apple', '2'),
('banana', '3'),
('banana', '4'),
('banana', '5')
ON KEY DUPLICATE UPDATE type = CONCAT(type, '|', VALUES(type))
唯一的问题是结果行是:
('apple', '1|2|2')
('banana', '3|4|5')
我正在尝试使用不同的DISTINCT方法来摆脱最后的'2',但我不断收到MySql错误
答案 0 :(得分:2)
MySQL的命令名为ON DUPLICATE KEY UPDATE
如果你想按照你显示的顺序(如('banana', '3|4|5')
)保留它,你应该像这样使用它:
ON DUPLICATE KEY UPDATE type = CONCAT(type, '|', VALUES(type))
因为VALUES
指的是试图插入现有记录的新值。
如果您想避免重复值,请尝试:
ON DUPLICATE KEY UPDATE type = IF(type LIKE CONCAT('%', VALUES(type), '%'), type, CONCAT(type, '|', VALUES(type)) )
我同意这不是处理数据库的最佳方法,但如果这是你想要的,这应该可以解决问题。
答案 1 :(得分:1)
插入数据与管道分离,您可以像往常一样将数据插入数据库:
create table test(id int, fruit varchar(50), type varchar(100));
INSERT INTO test (fruit, type) VALUES
('apple', '1'),
('apple', '2'),
('apple', '2'),
('banana', '3'),
('banana', '4'),
('banana', '5');
然后编写这样的查询以您想要的方式提取数据:
select fruit, group_concat(distinct type separator '|') as type
from test
group by fruit
Result:
fruit type
apple 1|2
banana 3|4|5
SQLFiddle示例:http://sqlfiddle.com/#!9/90a9b/1
您甚至可以创建这样的视图:
create view test_pipedelimited as
select fruit, group_concat(distinct type separator '|') as type
from test
group by fruit;
然后总是只使用以管道分隔格式获得结果
select * from test_pipedelimited
<强>程序强>
如果你真的真的想要存储带有管道分隔的类型,你可以通过这样的存储过程来实现:
delimiter //
create procedure insert_data_into_test (
p_fruit varchar(50), -- takes fruit as first argument
p_type varchar(100), -- takes type as second argument
OUT p_id int -- populates this variable with -1 if it was an update or with last inserted ID if it was an insert
)
begin
-- find out if the fruit is already in the table
declare fruit_count int;
select count(*) into fruit_count from test where fruit = p_fruit;
-- if fruit is in the table, do an update
if fruit_count > 0 then
update test set type = concat(type, '|', p_type) where fruit = p_fruit;
set p_id = -1;
-- if fruit is NOT in the table, do an insert
else
insert into test (fruit, type) values (p_fruit, p_type);
select last_insert_id() into p_id;
end if;
end; //
delimiter ;
您如何称呼此程序?
create table test (id int primary key auto_increment, fruit varchar(50), type varchar(100));
-- create the procedure here, technically
call insert_data_into_test('apple', '1', @id);
select @id;
Result: 1
select * from test;
ID fruit type
1 apple 1
call insert_data_into_test('apple', '2', @id);
select @id;
Result: -1
select * from test;
ID fruit type
1 apple 1|2
call insert_data_into_test('toast', '3', @id);
select @id;
Result: 2
select * from test;
ID fruit type
1 apple 1|2
2 toast 3
<强>建议强>
我强烈建议不要在数据库中存储这样的数据。通过有条理地存储数据并遵循一些已知的规范化规则,可以实现数据库的真正功能。这种技术违反了规范化的第一条规则(1NF)。
当您想避免插入重复类型时,它也会限制您。我们假设您输入apple
和1
,然后再次执行此操作。您将获得1|1
的类型。为了防止这种情况,你必须做更多的工作来找出类型中是否存在1。你不能只做LIKE type = '%1%'
,因为它会匹配1,11,21等。你不能很清楚地找出每种水果等的最大类型。
更好的程序
delimiter //
create procedure insert_data_into_test (
p_fruit varchar(50), -- takes fruit as first argument
p_type varchar(100), -- takes type as second argument
OUT p_id int -- populates this variable with -1 if it was an update or with last inserted ID if it was an insert
)
begin
-- find out if the fruit is already in the table
declare fruit_count int;
declare fruit_type_count int;
select count(*) into fruit_count from test where fruit = p_fruit;
-- if fruit is in the table, do an update
if fruit_count > 0 then
-- let's check if the the type is already there for the fruit
-- we don't want to put duplicates in
select count(*) into fruit_type_count
from test
where
fruit = p_fruit
and ( -- if p_type was 2
type regexp concat('^', p_type, '$') -- ^2$ regex matches if type starts and ends with 2
or type regexp concat('^', p_type, '\\|') -- ^2| regex matches if type starts with 2| (the \\ is to prevent MySQL from giving a special meaning to |)
or type regexp concat('\\|', p_type, '\\|') -- |2| regex matches if type is in the middle somewhere
or type regexp concat('\\|', p_type, '$') -- |2$ regex matches if type is at the end but there's something before it
);
-- only update type if the type is not already present
if fruit_type_count = 0 then
update test set type = concat(type, '|', p_type);
end if;
set p_id = -1;
-- if fruit is NOT in the table, do an insert
else
insert into test (fruit, type) values (p_fruit, p_type);
select last_insert_id() into p_id;
end if;
end; //
delimiter ;
这个更好的程序会导致重复,并且不会插入副本。