简体   繁体   English

MySQL如何将WHERE子句应用于除一个以外的所有选定列?

[英]MySQL How to apply WHERE clause to all selected columns except one?

I am totalling columns and grouping them by a column "fruits" like this: (based on my previous question on SO ) 我对列进行总计并按“水果”列将其分组,如下所示:(基于我之前对SO的提问

SELECT `fruits`, sum(amount), sum(price)
FROM `accounts` 
GROUP BY fruits

I have now added a date column to the table and i'm trying to filter the result by dates like this: 现在,我在表中添加了一个日期列,并且我试图按如下日期过滤结果:

SELECT `fruits`, sum(amount), sum(price)
FROM `accounts` 
WHERE `userid` = 1 AND `date` BETWEEN "2010-11-01" AND "2015-12-22"
GROUP BY fruits

This works fine and I get the filtered results. 这工作正常,我得到了过滤的结果。 However, if a fruit has not been entered between the two dates, it naturally doesn't show up because the WHERE clause also includes the fruits . 但是,如果在两个日期之间未输入水果,则自然不会显示,因为WHERE子句还包含该fruits

So, my question is how can I write a query where it gets all the fruits regardless of the dates but filters only the amount and price column by dates? 因此,我的问题是我该如何编写一个查询,在该查询中无论日期如何都能获得所有结果,但仅按日期过滤数量和价格列?

Theres' a couple of approaches. 有几种方法。 One is to use conditional aggregation. 一种是使用条件聚合。 Remove the predicate, and move the conditional test to an expression in the SELECT list. 删除谓词,然后将条件测试移动到SELECT列表中的表达式。 For example, something like this: 例如,如下所示:

SELECT a.fruits
     , SUM( IF(a.userid = 1 AND a.date BETWEEN '2010-11-01' AND '2015-12-22'
              ,a.amount,0)
       ) AS `tot_amount`
     , SUM( IF(a.userid = 1 AND a.date BETWEEN '2010-11-01' AND '2015-12-22'
              ,a.price,0)
       ) AS `tot_price`
  FROM `accounts` a
 GROUP BY a.fruits

Other approaches will use a row source that returns the values of fruits you want returned, and then an "outer join" to the totals from your original query. 其他方法将使用行源,该源返回要返回的fruits的值,然后对原始查询的总数返回“外部联接”。 Or for a reasonably small number of rows, you could use correlated subqueries in the SELECT list. 或者对于相当少的行数,可以在SELECT列表中使用相关的子查询。

Let's say that this returns the set of fruits you want to returned: 假设这返回要返回的一组fruits

SELECT s.fruits
  FROM `accounts` s
 GROUP BY s.fruits

We can wrap that in parens, and use it as a rowsource like it was a table. 我们可以将其包装在括号中,并像表一样将其用作行源。 As a trivial example of that: 作为一个简单的例子:

SELECT f.fruits
  FROM ( 
         SELECT s.fruits
           FROM `accounts` s
          GROUP BY s.fruits
       ) f

Now we could do the same thing with your original query, wrap it in parens and make it an inline view: 现在,我们可以对原始查询执行相同的操作,将其包装在括号中并使其成为内联视图:

SELECT f.fruits
     , IFNULL(t.tot_amount,0) AS tot_amount
     , IFNULL(t.tot_price,0)  AS tot_price
  FROM ( 
         SELECT s.fruits
           FROM `accounts` s
          GROUP BY s.fruits
       ) f
  LEFT
  JOIN (  
         -- original query here 
         SELECT a.`fruits`
              , sum(a.amount) AS tot_amount
              , sum(a.price) AS tot_price
           FROM `accounts` a
          WHERE a.`userid` = 1
            AND a.`date` BETWEEN '2010-11-01' AND '2015-12-22'
          GROUP BY a.fruits
       ) t
    ON t.fruits = f.fruits

You can do it using a left join: 您可以使用左联接来实现:

SELECT t.`fruits`,sum(coalesce(s.amount,0)),sum(coalesce(s.price,0))
FROM(SELECT DISTINCT `fruits` FROM `accouts`) t
LEFT OUTER JOIN `accounts` s
 ON(t.`fruits` = s.`fruits` AND s.`userid` = 1
    AND s.`date` BETWEEN "2010-11-01" AND "2015-12-22")
GROUP BY t.`fruits`

Try this: 尝试这个:

SELECT 
    `fruits`, 
    sum((`date` BETWEEN "2010-11-01" AND "2015-12-22") * amount) total_amount,
    sum((`date` BETWEEN "2010-11-01" AND "2015-12-22") * price) total_price
FROM `accounts` 
WHERE `userid` = 1
GROUP BY fruits

you can do by this one: 您可以通过以下方法做到:

SELECT a1.`fruits`, sum(a1.amount), sum(a1.price)
FROM `accounts` a1
LEFT OUTER JOIN `accounts` a2 ON a1.fruits = a2.fruits 
AND a2.`userid` = 1 AND a2.`date` BETWEEN "2010-11-01" AND "2015-12-22" 
GROUP BY a1.fruits

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM