0

在项目的设计模式中,一个product可能有多个images。

现在我想imageproducts 中选择 n s 的情况:

  • 如果定义了 s,则从每个n product中选择 1 。image
  • 否则image从每个product限制中选择更多n

我们是否还需要 PHP 辅助操作来达到目标​​?

架构符合预期:

product (id, title, ...)
image (id, product_id, filename, ...)

我什至无法想到这样的查询,这就是为什么我没有不幸尝试任何事情的原因。

查询应如下所示:

SELECT * FROM image ..with..those..hard..conditions.. LIMIT n
4

2 回答 2

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()太糟糕了,您不必在这里考虑“表演”;)

请注意,我没有完全测试过这个解决方案。让我知道是否有一些不工作的极端情况(好吧..任何情况)。

于 2013-07-29T13:02:57.213 回答
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比较小,您可能会受益于我从大表中选择随机行的技术:虽然它旨在选择单行,但它可以相对容易地适应选择一些随机行。

这是带有 Sylvain Leroux 示例的 SQL:

-- 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;
于 2013-07-29T13:58:15.217 回答