2

我在数据库的表中有4 个类别
我想从数据库中的每个类别中获取访问次数最多的四篇文章。
这意味着得到(4 articles most visited from category1)+ (4 articles most visited from category2)+ (4 articles most visited from category3)+ (4 articles most visited from category4)= Total 16 articlesfrom 4 categories

我想通过一个查询来做到这一点。

普通查询:

$sql="select ID,name,country from article where `active`='yes' order by `visit` desc limit 16 ";

文章表结构:

CREATE TABLE `article` (
  `ID` int(11) NOT NULL auto_increment,
  `name` varchar(255) NOT NULL default '',
  `country` varchar(50) NOT NULL default '',
  `town` varchar(30) NOT NULL default '',
  `other_town` varchar(30) NOT NULL default '',
  `title` varchar(255) NOT NULL default '0',
  `size` varchar(30) NOT NULL default '',
  `type` varchar(30) NOT NULL default '',
  `tel` varchar(30) NOT NULL default '',
  `mobile` varchar(30) NOT NULL default '',
  `connect` varchar(30) NOT NULL default '',
  `email` varchar(30) NOT NULL default '',
  `photo1` varchar(100) NOT NULL default '',
  `print` varchar(30) NOT NULL default '',
  `small_pic1` varchar(100) NOT NULL default '',
  `detail` text NOT NULL,
  `add_by` int(11) NOT NULL default '0',
  `cat` int(11) NOT NULL default '0',
  `goods_type` enum('new','old') NOT NULL,
  `add_date` date NOT NULL default '0000-00-00',
  `end_date` date NOT NULL default '0000-00-00',
  `period` varchar(30) NOT NULL default '',
  `visit` int(11) NOT NULL default '0',
  `comment` int(30) NOT NULL default '0',
  `fav` varchar(15) NOT NULL default '',
  `favorite` varchar(15) NOT NULL default '',
  `active` varchar(15) NOT NULL default '',
  `rate` int(11) NOT NULL default '0',
  `short` text NOT NULL,
  `add_to` varchar(50) NOT NULL default '',
  `author` varchar(50) NOT NULL default '',
  `author_img` varchar(50) NOT NULL default '',
  `lang` varchar(10) NOT NULL default '',
  `budget` varchar(50) NOT NULL default '',
  PRIMARY KEY  (`ID`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 ;

类别表结构:

CREATE TABLE `category` (
  `ID` int(11) NOT NULL auto_increment,
  `name` varchar(255) NOT NULL default '',
  `img` varchar(255) NOT NULL default '',
  `sub` int(11) NOT NULL default '0',
  `type` varchar(20) NOT NULL default '',
  `lang` varchar(10) NOT NULL default '',
  `active` varchar(25) NOT NULL default '',
  `add_by` int(11) NOT NULL default '0',
  PRIMARY KEY  (`ID`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;
4

3 回答 3

1

这可以做到,但不是 100% 直截了当。我从我以前读过的一个 SO 问题中为这篇文章添加了书签(也会尝试查找/链接)。基本上,如果您希望每个查询都使用这一组,您可以只使用 ORDER BY 和 LIMIT,但是要在一个查询中完成所有操作,请按照链接的文章进行详细介绍。

http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/

对于后代,我将尝试根据他提供的第一种方法发布一个示例摘要查询,该方法可以与类别数量成比例地随时间呈指数增长:

select ID, name, country, cat, visit
from article
where visit = (select max(visit) from article as a where a.cat = article.cat)
or visit = (select max(visit) from article as a where a.cat = article.cat
   and visit < (select max(visit) from article as a2 where a2.cat = article.cat))

or visit = (select max(visit) from article as a where a.cat = article.cat
  and a.visit < (select max(a2.visit) from article as a2 where a2.cat = article.cat
  and a2.visit < (select max(a3.visit) from article as a3 where a3.cat = article.cat)))

or visit = (select max(visit) from article as a where a.cat = article.cat
  and a.visit < (select max(a2.visit) from article as a2 where a2.cat = article.cat
  and a2.visit < (select max(a3.visit) from article as a3 where a3.cat = article.cat
  and a3.visit < (select max(a4.visit) from article as a4 where a4.cat =    article.cat))))
order by cat, visit desc

或者,如果您想要在不指定类别的情况下订购,只需访问 desc 订购

这将返回每个类别中的前四名,但请注意您要查找的每个级别的查询嵌套,如果您需要继续深入,请按照他的说明获取更好的选择(他,我将其描述为 YUCK) .

SQL小提琴:http ://www.sqlfiddle.com/#!2/e115f/26

同样为了后代,我的测试数据:

CREATE TABLE article (
 ID int auto_increment primary key, 
 name varchar(20), 
 country varchar(30),
 cat int,
 visit int
);

INSERT INTO article (name, country, cat, visit) VALUES
 ('Test1', 'Canada', 1, 7),('Test2', 'Canada', 1, 2),('Test3', 'Ireland', 1, 1),
 ('Test5', 'Ireland', 1, 3),('Test6', 'Ireland', 1, 8),('Test7', 'India', 1, 9),
 ('Test8', 'Canada', 2, 11),('Test9', 'Canada', 2, 13),('Test10', 'Ireland', 2, 6),
 ('Test11', 'Ireland', 2, 5),('Test12', 'Ireland', 2, 1),('Test13', 'India', 3, 1),
 ('Test14', 'India', 3, 9),('Test15', 'India', 3, 8),('Test16', 'India', 3, 54);
于 2013-02-13T15:59:51.860 回答
1

这应该这样做。基本上确定每个类别的行号,然后按访问列排序并选择前 4 个。这是一个精简版本,但应该明白这一点(添加您需要返回的字段):

SELECT Id, Cat, Visit, Name
FROM (
    SELECT 
      @curRow:=CASE WHEN @prevRow = A.cat THEN @curRow+1 ELSE 1 END AS rn,
      A.Id, 
      A.Visit,
      A.Cat, A.Name, 
      @prevRow:=A.cat AS clset
    FROM (SELECT A.Id, C.Id as Cat, A.Visit, C.Name
          FROM Articles A
            JOIN Category C ON A.cat = C.id
          ORDER BY A.Cat, A.Visit DESC
          ) A
      JOIN (SELECT @curRow:=0) r
      JOIN (SELECT @prevRow:=0) r2
  ) B
  WHERE rn <= 4

还有一些小提琴:http ://sqlfiddle.com/#!2/b7260/1

祝你好运。

于 2013-02-13T16:02:58.363 回答
0

尝试这个:

SELECT ID, NAME, country, catCnt 
FROM (SELECT ID, NAME, country, cat, IF(@cat=(@cat:=cat), @cnt:=@cnt+1, @cnt:=1) catCnt 
      FROM (SELECT ID, NAME, country, cat FROM article WHERE `active`='yes' ORDER BY cat, `visit` DESC) A, 
           (SELECT @cat := 0, @cnt:=1) B
      ) A 
GROUP BY cat HAVING catCnt <= 4;

或者

SELECT ID, NAME, country
FROM (SELECT ID, NAME, country, cat, IF(@cat=(@cat:=cat), @cnt:=@cnt+1, @cnt:=1) catCnt 
      FROM (SELECT ID, NAME, country, cat FROM article WHERE `active`='yes' ORDER BY cat, `visit` DESC) A, 
           (SELECT @cat := 0, @cnt:=1) B
      ) A 
WHERE catCnt <= 4;
于 2013-02-13T16:03:15.077 回答