在项目的设计架构中,一个product
可能有很多image
个。
现在我想从image
s中选择n product
s,情况如下:
n
product
,请从每个image
中选择image
。product
限制n
product (id, title, ...)
image (id, product_id, filename, ...)
s
我们是否还需要PHP侧行动来实现目标?
架构符合预期:
SELECT * FROM image ..with..those..hard..conditions.. LIMIT n
我甚至无法想到这样的查询,这就是为什么我不幸地尝试过任何事情。
查询应如下所示:
{{1}}
答案 0 :(得分:3)
如果我理解得很好 - 你需要n
张图片。如果可能,从不同的产品。否则,来自同一产品的多个图像可作为后备。
从现在开始,我能想到的唯一解决方案是构建一个临时表,其中包含编号行,例如每个产品的“图像”位于“顶部” - 并与其余部分一起提交图像。
构建该表后,您的查询只是SELECT ... LIMIT n
。
这将表现得非常糟糕 - 如果你选择了灵感的解决方案 - 你应该离线或按时合并图像表。
请参阅http://sqlfiddle.com/#!2/81274/2
--
-- test values
--
create table P (id int, title char(20));
insert into P values
(1, "product 1"),
(2, "product 2"),
(3, "product 3");
create table I (pid int, filename char(40));
insert into I values
(1, "image p1-1"),
(1, "image p1-2"),
(3, "image p3-1"),
(3, "image p3-2"),
(3, "image p3-3");
--
-- "ordered" image table
--
create table T(n int primary key auto_increment not null,
filename char(20));
--
-- consolidate images (once in a while)
--
delete from T;
insert into T(filename)
select filename from I group by pid;
insert into T(filename)
select filename from I order by rand();
--
-- do the actual query
--
select * from T limit n;
编辑这是一个完全不同的想法。不使用合并表/视图 - 所以这可能会被视为更好:
http://sqlfiddle.com/#!2/57ea9/4
select distinct(filename) from
(select 1 as p, filename from I group by pid
union (select 2 as p, filename from I order by rand() limit 3)) as T
order by p limit 3
这里的关键点是我不必真正“编号”行。仅跟踪来自第一个SELECT
的行。这就是p
的目的。为简单起见,我将LIMIT
子句设置为相同的值。我不认为你必须“优化”那部分,因为它的好处非常小 - ORDER BY RAND()
太可怕了,你不必在这里考虑“表演”;)
请注意我没有对此解决方案进行全面测试。让我知道是否有一些不合作的案例(好吧...... 任何案例)。
答案 1 :(得分:1)
http://sqlfiddle.com/#!2/32198/2/0
create view T as select (select filename from I where pid = id order by filename limit 1) as singleImage from P having singleImage is not null;
select * from (
select singleImage from T
union all (select filename from I where filename not in
(select singleImage from T) order by rand() limit 5)
) as MoreThanN limit 5;
如果您的N
相当小,您可能会受益于my technique for selecting random rows from large tables:虽然它旨在选择单行,但可以相对轻松地选择一些随机行。
这是SQL与Sylvain Leroux的例子:
-- Test values
create table P (id int, title char(20));
insert into P values
(1, "product 1"),
(2, "product 2"),
(3, "product 3");
create table I (pid int, filename char(40));
insert into I values
(1, "image p1-1"),
(1, "image p1-2"),
(3, "image p3-1"),
(3, "image p3-2"),
(3, "image p3-3"),
(3, "image p3-4"),
(3, "image p3-5");
-- View to avoid repeating the query
create view T as select (select filename from I where pid = id order by filename limit 1) as singleImage from P having singleImage is not null;
-- Query
select * from (
select singleImage from T
union all (select filename from I where filename not in
(select singleImage from T) order by rand() limit 5)
) as MoreThanN limit 5;