【问题标题】:Selecting first in each (SQL / PHP)在每个中选择第一个(SQL / PHP)
【发布时间】:2011-02-28 20:09:17
【问题描述】:

好的,我试着推迟并寻找答案,但我需要你们的帮助!我有三个表——类别、项目和图像。我进行了设置,以便将图像链接到特定项目,并且每个项目都有一个类别。我使用两个内部连接来做到这一点(这是正确的吗?)我最终想要做的是让 PHP 从每个项目中回显第一个图像,然后我将使用 ajax 来加载其余的图像项目。我看过 LIMIT ,我确信有一种方法可以使用 PHP 和 for 循环轻松完成,但我只是难住了!我怎样才能回显每个项目的第一个“文件名”?提前致谢!

表格:

CREATE TABLE `category` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

CREATE TABLE `project` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `caption` text NOT NULL,
  `category` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

CREATE TABLE `images` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `filename` varchar(255) NOT NULL,
  `project` int(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=13 DEFAULT CHARSET=latin1;

查询:

SELECT i.filename as filename,
          i.project as project_id,
          p.name as project_name,
          c.name as category

FROM images i

INNER JOIN project p
ON i.project = p.id

INNER JOIN category c
ON p.category = c.id

【问题讨论】:

  • GROUP BY 项目ID的结果。欢迎来到 SO。
  • 当你说“每个项目的第一个”时,你是什么意思?按名称排序?按身份证?
  • 观察:project.id 定义为 int(11)images.project 定义为 int(50)
  • @Linus Kleen 谢谢,我很惊讶帮助来得如此之快!如果我GROUP BY,那不是只返回他们组中的图像吗? (每个“项目”中的“文件名”)我如何只获得每个组中存储的第一个文件名?谢谢!
  • @ypercube 我猜是按 id 排序的,但我想我在想,无论哪个文件名在每个项目的第一行。我猜这意味着我应该有不同的计划?感谢您指出 int(50)- 没有意义!

标签: php mysql


【解决方案1】:

通常,您可以按特定列对查询结果进行分组。

这个没有GROUP BY 的查询更适合在项目中查找第一个图像:

SELECT @pid := `prj_id`, 
   (SELECT MIN(`id`) FROM `images` `i` WHERE `i`.`prj_id` = @pid) `first_img`
FROM `projects`

这还将选择根本没有图像的项目(即first_imgNULL)。 HAVING 子句过滤这些可能是必要的。

【讨论】:

  • 老实说,其中一些内容已经超出了我的想象,但我想我明白了其中的要点。 ;) 查询非常有帮助!我很好奇您关于如何设置查询的建议。所以我应该先选择所有项目,而不是从images 表中选择东西?我猜我迷失了顺序以及我到底应该加入什么。再次感谢 - 巨大的帮助!
  • 它会显示在“已编辑”的历史记录中,所以我刚刚删除了我对 INNER JOIN 的混乱咆哮等等,留下了实际的答案。
【解决方案2】:

在某个时候尝试 DISTINCT:

SELECT i.filename as filename,
          i.project as project_id,
          DISTINCT(p.name) as project_name,
          c.name as category

FROM images i

INNER JOIN project p
ON i.project = p.id

INNER JOIN category c
ON p.category = c.id

【讨论】:

  • 哇,这是一种完全不同的思考方式。有趣的!因此,假设我想使用 DISTINCT 来查找每个单独的项目,如果我在最后抛出 LIMIT 5 是否可以挑选出前 5 个不同的项目?
【解决方案3】:

我认为这仅适用于 MySQL,并且会为每个项目提供一个(随机)文件名:

SELECT i.filename as filename
     , i.project as project_id
     , p.name as project_name
     , c.name as category

  FROM images i
    INNER JOIN project p
      ON i.project = p.id
    INNER JOIN category c
      ON p.category = c.id

  GROUP BY p.id
;

这将选择具有最低 id 的文件名。我相信它可以在性能方面得到改进。我确实需要睡一会儿……

SELECT i.filename as filename
     , im.project_id
     , im.project_name
     , im.category

  FROM images i
    INNER JOIN 
    ( SELECT MIN(i.id) as id
           , i.project as project_id
           , p.name as project_name
           , c.name as category
        FROM images i
          INNER JOIN project p
            ON i.project = p.id
          INNER JOIN category c
            ON p.category = c.id
        GROUP BY p.id
    ) AS im
    ON i.id= im.id
;

【讨论】:

    【解决方案4】:

    你可以用这个:

    foreach ($Result as $r)
    {
    echo $r['picture'];
    break;
    }
    

    但这不会很好。你应该在SQL中使用LIMIT,LIMIT有什么问题吗?

    【讨论】:

    • 你也可以使用$r=next($Result);
    • 重点还应该是代码的效率,而不仅仅是它的工作。你们在这个回复中试图实现的编程方式不会使这个查询资源高效。
    • 大声笑。效率低下是当您获取 100 行并转储其中的 99 行以获得所需的 1 行时,而您可以编写正确的查询并获取所需的 1 行。
    • 我的 2c 在这里:我对 OP 问题的解读是如何使用 LIMIT(或其他方式)编写仅获取所需的 1 行所需的 SQL 查询。
    • SO 的常见问题解答指出,它是“专业和爱好者程序员” 的平台。不过,没有提到周围燃烧。我看到了很多热情,但绝对不是你们两个 cmet,@Shehi 和 @AbiusX 的专业精神。
    猜你喜欢
    • 2013-05-07
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多