【问题标题】:Showing Featured Item From the Database显示数据库中的特色项目
【发布时间】:2013-04-28 14:03:33
【问题描述】:

我有如下数据库表。

id, bungalow_name, type, address, featured 

平房可以在主页上显示。如果有特色的平房,featured 列的值为 1。我的桌子上有 50 间平房,并且在给定时间有 5-7 间平房。

假设特色平房名称如下。

bungalow 1, bungalow 2, bungalow 3, .........., bungalow 6

我要做的是在主页上显示每天的特色平房。我想每个月像下面这样循环。鉴于我不想为每个页面加载随机显示平房。我想每天展示一间平房。

today              -> bungalow 1
tomorrow           -> bungalow 2
day after tomorrow -> bungalow 3
...
After bungalow 6, bungalow 1 is shown on the next day.

我该怎么做?甚至可以使用 SQL/PHP 吗?

【问题讨论】:

  • 有趣!好吧,只需在表中记录所有特色平房。使用系统时间()每天显示不同的特色平房。每次日期递增时,都会增加一个变量,直到特色平房的数量。
  • 我们正在尝试类似的有趣问题,我们有时间范围,让我给你我的数据,你可以建立你自己的查询。好的,我们在这里使用了stackoverflow.com/questions/9604391/…,它带着微笑工作:)
  • 我几乎会考虑做一个特色模块,类似于新闻快讯,但修改查询以仅使用特色。
  • Dasun 是否像内容一样使用单独的表格来管理排序?
  • 不,我不使用单独的表。但如果需要可以添加

标签: php mysql sql joomla logic


【解决方案1】:

你可以使用这个 MySQL 查询:

SELECT *
FROM Bungalows
WHERE id = (
  SELECT b1.id
  FROM
    Bungalows b1 LEFT JOIN Bungalows b2
    ON b1.id>b2.id AND b2.featured=1
  WHERE
    b1.featured=1
  GROUP BY
    b1.id
  HAVING
    COUNT(b2.id) = (SELECT
                      DATEDIFF(CURDATE(), '2013-05-06') MOD
                      (SELECT COUNT(*) FROM Bungalows WHERE Featured=1))
  )

请看小提琴here。 '2013-05-06' 是您想要开始展示第一个特色平房的日子。它们将按 ID 排序显示,从“2013-05-06”开始。

编辑

以下查询将返回自 2013-05-06 以来经过的天数:

SELECT DATEDIFF(CURDATE(), '2013-05-06')

MOD 函数将返回经过天数除以特征行数的整数余数:

SELECT DATEDIFF(CURDATE(), '2013-05-06') MOD
                          (SELECT COUNT(*) FROM Bungalows WHERE Featured=1)

如果有 6 个特色平房,则第一天返回 0,第二天返回 1,2,3,4,5,然后再次返回 0,1,2...。

MySQL 没有返回 RANK(行数)的函数,因此您必须以某种方式模拟它。我是这样模拟的:

SELECT b1.id, COUNT(b2.id)
FROM
  Bungalows b1 LEFT JOIN Bungalows b2
  ON b1.id>b2.id AND b2.featured=1
WHERE
  b1.featured=1
GROUP BY
  b1.id

我正在加入 Bungalows 表。 bungalow ID 的排名是 ID 小于该 ID 的 bungalow 的数量(因此加入 b1.id>b2.id)。

然后我只选择上面函数返回 RANK 的行:

拥有 计数(b2.id)=(选择 DATEDIFF(CURDATE(), '2013-05-06') MOD (SELECT COUNT(*) FROM Bungalows WHERE Featured=1))

如果你使用 MySQL,我的初始查询可以简化为:

SELECT b1.*
FROM
  Bungalows b1 LEFT JOIN Bungalows b2
  ON b1.id>b2.id AND b2.featured=1
WHERE
  b1.featured=1
GROUP BY
  b1.id
HAVING
  COUNT(b2.id) = (SELECT
                    DATEDIFF(CURDATE(), '2013-05-06') MOD
                    (SELECT COUNT(*) FROM Bungalows WHERE Featured=1))

【讨论】:

  • 您能否添加更多详细信息来解释其工作原理?
  • @Dasun 添加了解释,如果有不清楚的地方请告诉我
【解决方案2】:
$dbh = new PDO(....); // use your connection data
$statement = $dbh->query("SELECT count(*) as size FROM bungalows where features = 1");
$data = $statement->fetchALL(PDO::FETCH_CLASS,"stdClass");
$i = date('z') % $data[0]->size;

$statement = $dbh->query("SELECT * FROM bungalows where features = 1 order by id LIMIT $i,1");
$bungalow = reset($statement->fetchALL(PDO::FETCH_CLASS,"stdClass"));

编辑

  • 删除了 mysql_ 调用
  • 按照 fthiella 的建议添加了一个订单条款(谢谢 :))

【讨论】:

  • 好主意 :) 仅使用 MySQL 查询并不是那么容易,但是使用 MySQL+PHP 使事情变得更容易... +1... 我建议通过SELECT * FROM bungalows WHERE featured=1 ORDER BY id ... 添加订单,因为SQL 表默认不排序
【解决方案3】:

试试这个查询,随着特色平房等数量的增加,它会在任何情况下都有效 并且每天都会给出一个不同的。

在查询中,我为每个特色平房分配数字,从 0 到 n,然后通过将特色平房的总数除以日期差异来接收,我发现要显示的平房。

查询 1:

select 
   a.* 
from 
   (select 
      @rn:=@rn+1 as rId, 
      b.cnt,  
      a.* 
   from 
      Bunglows a
   join 
      (select @rn:=-1) tmp
   join
      (select 
         count(*) as cnt 
      from 
         Bunglows 
      where 
         featured=1)b
   where 
      featured=1) a
where  
   datediff(CURDATE(), '2013-01-01')%a.cnt=a.rId

SQL FIDDLE:

| RID | CNT | ID | BUNGALOW_NAME | FEATURED |
---------------------------------------------
|   3 |   4 |  6 |    bungalow 4 |        1 |

编辑

select count(*) as cnt from Bunglows where featured=1

此查询查找所有特色平房

select @rn:=@rn+1 as rId, b.cnt, a.* from Bunglows a join (select @rn:=-1) tmp join     select count(*) as cnt from Bunglows where featured=1

此查询将一个行号添加到从 0 到 n 开始的每个特色平房

主查询首先找到当前日期和旧日期的日期差异,并通过总特色平房查找 mod 值,这将给出从 0 到 n-1 的值,我添加了一个 where 子句来检查划分的值是否为等于我们分配的rowid..

希望这会有所帮助...

【讨论】:

  • 您能否添加更多详细信息来解释其工作原理?
  • 这真的不是您在 Joomla 中的做法。首先你会使用 jdatabasequery。
【解决方案4】:

我的回答的基本概念是;

1/ 创建所有特色平房的列表。这是在子查询中实现的,其中每个平房都有一个唯一的序列号。 seq_num 字段的代码基于答案here

2/ 根据我们在当月的位置从列出的平房中选择一个平房。为此,我使用代码day(curdate()) 查看今天的日期,然后找到该数字与特色平房总数的模数。

select  sq.bungalow_name
from    (
        select  bungalow_name
                ,@curRow := @curRow + 1 AS seq_num
        from    table1, (SELECT @curRow := 0) r
        where   featured = 1
        order by
                bungalow_name desc
        ) sq
where   sq.seq_num = mod(day(curdate()),(select count(*) from table1 where featured = 1))

这个例子SQL Fiddle

【讨论】:

    【解决方案5】:

    您必须跟踪每条精选记录的最后显示日期 (last_viewed)。 对于新记录,将此日期设置为过去的一天,例如。 2000-01-01。 如果有当前日期的记录,请使用它。 如果不是,请使用日期最早的记录。

    SELECT *, IF(DATE(last_viewed)=CURDATE(), 1, 0) AS current
       FROM #__bungalows
       WHERE featured=1
       ORDER BY current DESC, last_viewed ASC
       LIMIT 0,1
    

    与com_content 中的hit 计数器一样,您应该为您的bungalow 模型添加一个hit 方法,将所选bungalow 的last_viewed 列设置为now()。

    【讨论】:

      【解决方案6】:
      select ....
      
      where featured = 1
      limit DAYOFYEAR(NOW()) % (select count(*) from ... where featured = 1), 1
      

      我不确定是否允许在限制范围内进行子选择。您可能必须单独执行该查询。这将每天轮换。易榨柠檬汁。

      编辑:在 2 个查询中执行

      $query = "SELECT COUNT(*) FROM ... WHERE FEATURED = 1";
      $count = intval(array_pop(mysql_fetch_assoc(mysql_query($query))));
      
      $query = "
      select ....
      
        where featured = 1
        limit DAYOFYEAR(NOW()) % {$count}, 1
      ";
      

      完成!

      【讨论】:

      • 你不能在限制子句中嵌套查询(要实现类似的东西你需要一个准备好的语句)
      • 好的,还有另一种方法:按 rand(dayofyear(now)) 限制 1 排序——这将每天随机选择一个。也许有更好的方法,因为它有可能会选择两次。
      • “鉴于我不想在每次页面加载时随机显示一个平房。我想每天显示一个平房。”
      • 是的,它不是完全随机的。每天随机一次,我认为符合描述。它不是“随机加载每个页面”。我认为这是交流的重点,但谁知道呢? :P
      【解决方案7】:

      模运算符 % 可以解决问题:

      首先,添加一列“counter int”。

      接下来,将特色列编号为 1、2、3……如果你很懒,可以使用:

      set @cc=0;
      update bungalows set counter=(select @cc:=@cc+1) where featured=1;
      

      现在,一切准备就绪,您只需进行第一次选择:

      select * from bungalows where featured=1 and counter%(select count(*) from bungalows where featured=1)=0;
      

      每次您需要下一个特色平房之前,请执行以下操作:

      update bungalows set counter=counter+1 where featured=1;
      

      再说一遍:

      select * from bungalows where featured=1 and counter%(select count(*) from bungalows where featured=1)=0;
      

      ...

      update bungalows set counter=counter+1 where featured=1;
      

      等等……

      【讨论】:

        【解决方案8】:

        在这里查看SQLFiddle

        SELECT *
        FROM bungalows b
          JOIN (SELECT
                  ( DAYOFMONTH(CURDATE() ) % COUNT(b2.id) ) AS slab,
                  COUNT(b2.id) AS total_count
                FROM bungalows b2
                WHERE b2.featured = 1) AS b3
        WHERE IF(b3.slab = 0, b3.total_count, b3.slab) = (SELECT
                                                            COUNT(id)
                                                          FROM bungalows b1
                                                          WHERE b.id >= b1.id
                                                              AND b1.featured = 1)
            AND b.featured = 1
        

        【讨论】:

          猜你喜欢
          • 2018-10-23
          • 2019-08-02
          • 1970-01-01
          • 1970-01-01
          • 2018-05-14
          • 1970-01-01
          • 1970-01-01
          • 2013-04-20
          • 2015-09-22
          相关资源
          最近更新 更多