Mysql 按顺序分组-选择与查看
我得到了一些1:N的产品表及其图像表。为简单起见,只需:Mysql 按顺序分组-选择与查看,mysql,Mysql,我得到了一些1:N的产品表及其图像表。为简单起见,只需: create table t_Product( ID int not null, Name varchar(255), primary key (ID) ); create table t_Images( ID int not null, PID int not null, IsDefault int, primary key (ID), foreign key (PID) references t_Product (ID) ); ins
create table t_Product(
ID int not null,
Name varchar(255),
primary key (ID)
);
create table t_Images(
ID int not null,
PID int not null,
IsDefault int,
primary key (ID),
foreign key (PID) references t_Product (ID)
);
insert into t_Product (ID, Name) values (1, 'test1');
insert into t_Product (ID, Name) values (2, 'test2');
insert into t_Images (ID, PID, IsDefault) values (1, 1, 1);
insert into t_Images (ID, PID, IsDefault) values (2, 1, 0);
insert into t_Images (ID, PID, IsDefault) values (3, 2, 0);
insert into t_Images (ID, PID, IsDefault) values (4, 2, 1);
现在,我做了一个选择,它完全符合我的需要,从每个产品中选择默认图像或第一个图像:
select
I.*
from
(
select
ID,
PID,
IsDefault
from
t_Images
order by
PID asc,
IsDefault desc,
ID asc
) I
group by
I.PID
ID PID IsDefault
1 1 1
4 2 1
现在,我从“内部选择”创建一个视图:
create view v_Images
as
select
ID,
PID,
IsDefault
from
t_Images
order by
PID asc,
IsDefault desc,
ID asc
但选择此视图不适用于按以下方式分组时的排序:
select
VI.*
from
v_Images VI
group by
VI.PID
ID PID IsDefault
1 1 1
3 2 0
但如果我先从“选择自”视图中选择,然后再选择“分组依据”,它会再次工作:
select
VI2.*
from
(
select
VI.*
from
v_Images VI
) VI2
group by
VI2.PID
ID PID IsDefault
1 1 1
4 2 1
有人能给我解释一下,为什么分组选择的结果与视图不同,为什么它在双选视图上再次工作?这是您的问题:
select I.*
from (select ID, PID, IsDefault
from t_Images
order by PID asc, IsDefault desc, ID asc
) I
group by I.PID;
虽然这不是一个不常见的公式,但它使用了MySQL明确警告不要使用的构造。以下是相关部分的全文重点是我的:
要使查询合法,必须从
在GROUPBY子句中选择list或NAME
MySQL扩展了GROUPBY的使用,以便选择列表可以引用
GROUP BY子句中未命名的未聚合列。这意味着
前面的查询在MySQL中是合法的。您可以使用此功能
通过避免不必要的列排序和
分组。但是,这主要是在每个
未在GROUP BY中命名的未聚合列对于每个列都是相同的
组服务器可以从每个组中自由选择任何值,因此
除非它们相同,否则选择的值是不确定的
因此,尽管查询似乎可以工作,但文档警告不要这样做。我认为这种做法不好。另外,这是一个只在MySQL中工作的东西。其他数据库不允许此构造。而且,ANSI也有类似的ish功能,涉及具有功能依赖性的列,您可能会面临未来版本的MySQL将支持此合理功能的风险,从而使此方法无效
我的建议是使用一种合理的方法,这种方法不仅在MySQL中表现良好,而且符合ANSI标准。比如:
select ti.*
from t_Images ti
where not exists (select 1
from t_images ti2
where ti2.pid = ti.pid and
(ti2.IsDefault > ti.IsDefault or
(ti2.IsDefault = ti.IsDefault and
ti2.Id < ti.Id
)
)
)
设置sql_模式='ONLY_FULL_GROUP_BY';
select ti.*
from t_Images ti
where not exists (select 1
from t_images ti2
where ti2.pid = ti.pid and
(ti2.IsDefault > ti.IsDefault or
(ti2.IsDefault = ti.IsDefault and
ti2.Id < ti.Id
)
)
)
select pid, max(IsDefault) as IsDefault,
substring_index(group_concat(id order by isDefault desc id asc), ',', 1) as id
from ti_images
group by pid;