【问题标题】:Working with oldest datetimes for multiple columns使用多列的最旧日期时间
【发布时间】:2014-06-14 23:00:09
【问题描述】:

我的表包含 10 个日期时间列 (item1 - item10),代表我的成员提供的 10 项服务。在任何给定的“市/县”中,10 种服务中的每一种都只有 12 个职位。基本上,我需要将每列中最旧的十二个日期时间分别返回为“item1”、“item2”、“item3”等,否则返回为“”。

item#'s 回显到成员的列表中,我使用 jquery 过滤列表。

我当前的代码设置了一个限制,但不是根据日期时间。如果页面上的所有位置都已填满,则会出现问题。如果高级成员决定提供额外服务,他们可以“淘汰”新成员。

如果我没有很好地解释这一点,这里有一个工作示例: http://integritycontractingofva.com/pest_control/Richmond_VA.php

$result = @mysqli_query($db, "SELECT * FROM table WHERE category LIKE '%$category%' AND territories LIKE '%$area.%' AND exp >= NOW()");
if (!$result){echo ("<p>Error performing listing query:" . mysql_error() . "</p>");}

$item1cnt = $item2cnt = $item3cnt = $item4cnt = $item5cnt = $item6cnt = $item7cnt = $item8cnt = $item9cnt = $item10cnt = 0;   //start counter at "0"
$items = array();
$today = date('Y-m-d');
  while ($row = mysqli_fetch_array($result)){
    if($row["exp"] > $today){

      if($row["item1"]!="0000-00-00 00:00:00"){ // if datetime is set
        $item1cnt++;                            // add one to counter
        if($item1cnt > 12){                     // if counter is greater than 12
          $row["item1"]="";                     // itemx = ""
        }else{                                  // if counter is less than 12
          $row["item1"]="item1";                // item = itemx
        }
      }else{                                    // if datetime is not set
          $row["item1"]="";                     // itemx = ""
       }

// repeat above for all 10 items


// part of member's listing used by jquery to filter services
  $items[] = "<li class=\"services " . $row["item1"] . " " . $row["item2"] . " " . $row["item3"] . " " . $row["item4"] . " " . $row["item5"] . " " . $row["item6"] . " " . $row["item7"] . " " . $row["item8"] . " " . $row["item9"] . " " . $row["item10"] . "\">";

  }
}

如果成员为item1item3item9 设置了日期时间,则打印结果将为&lt;li class="services item1 item3 item9"&gt;

【问题讨论】:

  • 天哪,您介意更好地格式化您的代码以使其更具可读性吗?
  • 我想这应该在纯 MySQL 中以某种方式完成,而不是遍历表的所有记录。为了让您了解更改 SQL 以选择最后 10 个(项目)* 12(实体)= 最多 120 条记录,就像这样 SELECT * FROM table WHERE ... ORDER BY item1 desc, item2 desc, ..., item10 desc LIMIT 120; 这样您至少可以将您的提取减少到最多 120 条记录。
  • 为了清楚起见,我已经编辑了代码。我喜欢你添加 LIMIT 的想法。
  • 并在 SQL 中添加WHERE exp&gt;NOW()(我理解的只是未过期的许可证),而您不必在 PHP 中这样做。 PHP 应该只接收必要的数据记录。
  • 所以你不需要这行if($row["exp"] &gt; $today)

标签: php mysql datetime


【解决方案1】:

不确定这是否可行,也不确定性能,但您可以尝试类似的方法。

SELECT
    t.*,
    CONCAT_WS(' ',
        a1.class,
        a2.class,
        ...
        a10.class
    ) AS class
FROM table t
    LEFT JOIN (SELECT id,'item1' AS class FROM table ORDER BY item1 desc LIMIT 12) a1 ON t.id=a1.id
    LEFT JOIN (SELECT id,'item2' AS class FROM table ORDER BY item2 desc LIMIT 12) a2 ON t.id=a2.id
    ...
    LEFT JOIN (SELECT id,'item10' AS class FROM table ORDER BY item10 desc LIMIT 12) a10 ON t.id=a10.id

所有这些

if($row["item1"]!="0000-00-00 00:00:00"){ // if datetime is set
    $item1cnt++;                          // add one to counter
    if($item1cnt > 12){                   // if counter is greater than 12
        $row["item1"]="";                 // itemx = ""
    }else{                                // if counter is less than 12
        $row["item1"]="item1";            // item = itemx
    }
}else{                                    // if datetime is not set
    $row["item1"]="";                     // itemx = ""
}
// repeat above for all 10 items

可以简单地写成这样(对于所有 10 个元素):

// config
$item_count = 10;
$show_records = 12;
// process
$cnt = array_fill(1, $item_count, 0);
for ($i = 1; $i <= $item_count; $i++) {
    $n = "item" . $i;
    if (!$row[$n] || $row[$n] === "0000-00-00 00:00:00" || $cnt[$i] >= $show_records) {
        $row[$n] = "";
    } else {
        $cnt[$n]++;
    }
}

最终解决方案:

// === SELECTING ===
$result = mysqli_query($db, "
    SELECT
        t.*,
        CONCAT_WS(' ',
            a1.class,
            a2.class,
            ...
            a10.class
        ) AS classes
    FROM table t
        LEFT JOIN (SELECT id,'item1' AS class FROM table ORDER BY item1 desc LIMIT 12) a1 ON t.id=a1.id
        LEFT JOIN (SELECT id,'item2' AS class FROM table ORDER BY item2 desc LIMIT 12) a2 ON t.id=a2.id
        ...
        LEFT JOIN (SELECT id,'item10' AS class FROM table ORDER BY item10 desc LIMIT 12) a10 ON t.id=a10.id
    WHERE
        t.category LIKE '%$category%'
        AND t.territories LIKE '%$area.%'
        AND t.exp >= NOW()    
");
if (!$result){
    echo ("<p>Error performing listing query:" . mysql_error() . "</p>");
    exit;
}

// === PARSING ===

// config
$item_count = 10;
$show_records = 12;
// process
$cnt = array_fill(1, $item_count, 0);
for ($i = 1; $i <= $item_count; $i++) {
    $n = "item" . $i;
    if (!$row[$n] || $row[$n] === "0000-00-00 00:00:00" || $cnt[$i] >= $show_records) {
        $row[$n] = "";
    } else {
        $cnt[$n]++;
    }
}

// part of member's listing used by jquery to filter services
$items[] = '<li class="services ' . $row['classes'] . '">';

附:在将它们注入 SQL 查询之前,如果是用户输入,您应该正确地转义 $category$area。这可以通过mysql_real_escape 完成。

【讨论】:

  • 我会在接下来的几天里玩弄这个......当我的大脑再次开始燃烧时!!!最好使用查询来完成这项工作,而不是操纵结果:)
  • array_fill 加上一个,以及异常的简化!现在我想知道是否可以将每一列 (itemx) 日期时间放入一个数组中,将各个“itemx”的值赋予最旧的 12,而其他的值为“”,然后在 while 循环中使用修改后的数组创建列表。
  • 不确定你想用它来完成什么。获取最早的日期?然后只需将ORDER BY 交换为asc 就可以了。
  • 简单地说,使用各自成员的标签,使每个具有 12 个最旧日期的 itemx(服务)都可搜索。因此,服务有“高级感”,而不是成员......每种服务都有一种先到先得的想法。我发誓它在我的脑海中更加清晰!
  • (...) AS classes 将为您计算的“列”定义别名,因此您可以通过$row['classes'] 获取其值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-09
  • 2020-03-10
  • 1970-01-01
  • 1970-01-01
  • 2017-02-05
  • 2017-03-23
  • 2020-12-24
相关资源
最近更新 更多