对现有 SQL 结果执行查询?从 SQL 结果的子集中查找结果

鳄鱼

我有一个脚本可以遍历所有订单历史记录。打印结果需要几分钟,但我注意到我执行了几个足够相似的 SQL 语句,我想知道您是否可以对现有 SQL 结果执行另一个查询。

例如:

-- first SQL request
SELECT * FROM orders
WHERE status = 'shipped'

然后,在 foreach 循环中,我想从这个结果中找到信息。我天真的方法是执行这三个查询。请注意与上述查询的相似性。

-- grabs customer's LTD sales
SELECT SUM(total) FROM orders
WHERE user = :user
AND status = 'shipped'    

-- grabs number of orders customer has made
SELECT COUNT(*) FROM orders
WHERE user = :user
AND status = 'shipped'
AND total != 0

-- grabs number of giveaways user has won
SELECT COUNT(*) FROM orders
WHERE user = :user
AND status = 'shipped'
AND total = 0

当我寻求的结果是第一个查询的子集时,我最终会多次查询同一个表。我想在不执行更多 SQL 调用的情况下从第一个查询中获取信息。一些伪代码:

$stmt1 = $db->prepare("
    SELECT * FROM orders
    WHERE status = 'shipped'
");
$stmt1->execute();

foreach($stmt1 as $var) {
    $username = $var['username'];

    $stmt2 = $stmt1->workOn("
        SELECT SUM(total) FROM this
        WHERE user = :user
    ");
    $stmt2->execute(array(
        ':user' => $username
    ));
    $lifesales = $stmt2->fetchColumn();

    $stmt3 = $stmt1->workOn("
        SELECT COUNT(*) FROM this
        WHERE user = :user
        AND total != 0
    ");
    $stmt3->execute(array(
        ':user' => $username
    ));
    $totalorders = $stmt3->fetchColumn();

    $stmt4 = $stmt1->workOn("
        SELECT COUNT(*) FROM this
        WHERE user = :user
        AND total = 0
    ");
    $stmt4->execute(array(
        ':user' => $username
    ));
    $totalgaws = $stmt4->fetchColumn();

    echo "Username: ".$username;
    echo "<br/>Lifetime Sales: ".$lifesales;
    echo "<br/>Total Orders: ".$totalorders;
    echo "<br/>Total Giveaways: ".$totalgaws;
    echo "<br/><br/>";
}

这样的事情可能吗?它更快吗?我现有的方法又慢又丑,我想要一种更快的方法来做到这一点。

斯宾塞7593

我们可以对表进行一次遍历以获取所有用户的所有三个聚合:

SELECT s.user
     , SUM(s.total)        AS `ltd_sales`
     , SUM(s.total <> 0)   AS `cnt_prior_sales`
     , SUM(s.total  = 0)   AS `cnt_giveaways`
  FROM orders s
 WHERE s.status = 'shipped'
 GROUP
    BY s.user

在大型集上,这将是昂贵的。但是,如果我们需要为所有订单、所有用户使用它,这可能比执行单独的相关子查询要快。

带有前导列的索引user将允许 MySQL 使用该索引进行GROUP BY操作。在索引中包含statustotal列将允许完全从索引中满足查询。(使用status上的相等谓词,我们还可以尝试使用status作为前导列,然后是user列,然后是total.

如果我们只需要一小部分用户的结果,例如我们只从第一个查询中获取前 10 行,那么运行单独的查询可能会更快。我们只是将条件WHERE s.user = :user合并到查询中,就像在原始代码中一样。但是只运行一个查询而不是三个单独的查询。


我们可以将它与第一个查询结合起来,将其放入内联视图中,将其包装在括号中并将其FROM作为行源放入子句中

SELECT o.*

     , t.ltd_sales
     , t.cnt_prior_sale
     , t.cnt_giveaways

  FROM orders o 

  JOIN ( 
         SELECT s.user
              , SUM(s.total)        AS `ltd_sales`
              , SUM(s.total <> 0)   AS `cnt_prior_sales`
              , SUM(s.total  = 0)   AS `cnt_giveaways`
           FROM orders s
          WHERE s.status = 'shipped'
          GROUP
             BY s.user
      ) t
   ON t.user = o.user 

WHERE o.status = 'shipped'

我不确定名为“先前”销售的那一栏......这是返回所有已发货的订单,而不考虑比较任何日期(订单日期、履行日期、发货日期),我们通常会将其与什么“先前”的意思。


跟进

注意到问题被修改,status = 'shipped'从用户所有订单的计数中删除条件“ ”...

我会注意到我们可以将条件从WHERE子句移动到条件聚合中。

并不是说 OP 需要所有这些结果,而是作为演示......

SELECT s.user
     , SUM(IF(s.status='shipped',s.total,0))       AS `ltd_sales_shipped`
     , SUM(IF(s.status<>'shipped',s.total,0))       AS `ltd_sales_not_shipped`

     , SUM(s.status='shipped' AND s.total <> 0)   AS `cnt_shipped_orders`
     , SUM(s.status='canceled')                   AS `cnt_canceled`

     , SUM(s.status='shipped' AND s.total  = 0)   AS `cnt_shipped_giveaways`
  FROM orders s
 GROUP
    BY s.user

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在结果集中查找SQL值

来自分类Dev

使用查询结果更新现有表SQL Server 2012

来自分类Dev

使用查询结果更新现有表SQL Server 2012

来自分类Dev

SQL 从结果集中连接结果

来自分类Dev

SQL(服务器):将查询结果复制到现有表中,并带有查询结果的结构

来自分类Dev

使用sql更新带有选择查询结果的现有列

来自分类Dev

没有来自SQL查询的结果

来自分类Dev

SQL查询没有给出正确的结果

来自分类Dev

SQL查询的结果中有重复的行

来自分类Dev

SQL、CUCM:查询返回没有结果

来自分类Dev

SQL查询显示结果

来自分类Dev

连接SQL查询的结果

来自分类Dev

SQL空查询结果

来自分类Dev

SQL查询的ORDER BY结果

来自分类Dev

SQL查询重复结果

来自分类Dev

SQL查询结果结构

来自分类Dev

SQL查询结果重复

来自分类Dev

SQL查询-限制结果

来自分类Dev

SQL查询结果错误

来自分类Dev

Sql查询结果问题

来自分类Dev

SQL - 有结果的分组

来自分类Dev

SQL查询执行实体框架的匿名类型结果

来自分类Dev

如何计算已经执行的SQL查询的不同结果?

来自分类Dev

在sql server中执行查询后如何给结果赋予数字?

来自分类Dev

SQL查询:[计算查询结果]

来自分类Dev

填写SQL查询结果集中的缺失(时间段)行

来自分类Dev

填写SQL查询结果集中的缺失(时间段)行

来自分类Dev

如何创建连接和解析结果集中值的 SQL 查询

来自分类Dev

SQL从多行查找仲裁结果