4

我无法在 Mysql 中获取子查询。相当简单的都可以,而且我发现的大多数教程很少超出典型:

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);

我试图从我的数据库中提取的内容如下(我将尽我所能解释这一点,而无需任何关于我们数据库的背景知识):

检索属于特定代表的客户列表和上个月的总支出(在一个列中)和当月至今的支出金额,在另一列中。

结果,大致如下:

ID | NAME   | PREV MONTH | CUR MONTH
1  | foobar | £2300      | £1200
2  | barfoo | £1240      | £500

我用来获取第一部分数据的查询如下:

SELECT c.id,c.name, SUM(co.invoicetotal) as total
FROM customers as c
JOIN customerorders as co on co.customer_id = c.id
WHERE c.salesrep_id = 24
AND co.orderdate BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND CURDATE()
GROUP by c.id
order by total desc

DATE_SUB 可以替换为实际日期,因为 php 变量最终会出现在这里。作为一个例子,这只是给了我有效的数据。

这给了我,例如:

ID | NAME   | TOTAL 
1  | foobar | £2300      
2  | barfoo | £1240   

因此,理想情况下,我的子查询将是完全相同的查询,但日期已更改。我不断收到#1242 - Subquery returns more than 1 row 错误消息。

请问有什么建议或意见吗?

提前致谢。抢

4

5 回答 5

5
SELECT  c.id, c.name,
        (
        SELECT  SUM(co.invoicetotal)
        FROM    customerorders co
        WHERE   co.customer_id = c.id
                AND co.orderdate BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND CURDATE()
        ) AS prev_month,
        (
        SELECT  SUM(co.invoicetotal)
        FROM    customerorders co
        WHERE   co.customer_id = c.id
                AND co.orderdate BETWEEN CURDATE() AND CURDATE() + INTERVAL 1 MONTHS
        ) AS cur_month,
FROM    customers as c
WHERE   c.salesrep_id = 24
ORDER BY
        prev_month DESC
于 2010-08-16T16:16:30.020 回答
1

您收到错误的原因是:

WHERE column1 = (SELECT column1 FROM t2)

t2.column1返回多个结果,但由于子查询之前的等号运算符 - 只能接受一个值。

因此,您要么需要将其更改为 IN:

WHERE column1 IN (SELECT column1 FROM t2)

...接受多个值。或者将子查询更改为仅返回一个变量 - 此示例返回t2.column1整个表的最大值:

WHERE column1 = (SELECT MAX(column1) FROM t2)

这完全取决于您要获取的数据。

于 2010-08-16T16:13:53.417 回答
1

我省略了日期计算,因为您是从代码生成的:

SELECT c.id,c.name, 
    SUM(case when co.orderdate >= @LastMonthStartDate and co.orderdate < @CurrentMonthStartDate then co.invoicetotal else 0 end) as LastMonthTotal,
    SUM(case when co.orderdate between @CurrentMonthStartDate and CURDATE() then co.invoicetotal else 0 end) as CurrentMonthTotalToDate
FROM customers as c 
JOIN customerorders as co on co.customer_id = c.id 
WHERE c.salesrep_id = 24 
   AND co.orderdate BETWEEN @LastMonthStartDate AND CURDATE() --remove this if you want customers that did not order in the last 2 months
GROUP by c.id 
order by total desc 
于 2010-08-16T16:17:34.437 回答
0

OMG Ponies 关于你为什么会出现这个错误是正确的。在比较中使用的子查询必须始终返回单个值。

我的猜测是您需要创建两个子查询(一个用于 prev,一个用于 curr)并通过用户 ID 加入它们。像这样的东西:

SELECT prev.id,prev.name, prev.total, curr.total
FROM
(
SELECT c.id,c.name, SUM(co.invoicetotal) as total  
FROM customers as c JOIN customerorders as co on co.customer_id = c.id  
WHERE c.salesrep_id = 24  
AND co.orderdate BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND CURDATE()  
GROUP by c.id ORDER BY total desc  
) as prev
JOIN
(
SELECT c.id,c.name, SUM(co.invoicetotal) as total  
FROM customers as c JOIN customerorders as co on co.customer_id = c.id  
WHERE c.salesrep_id = 24  
AND co.orderdate > CURDATE()
GROUP by c.id ORDER BY total desc  
) as curr
ON prev.id=curr.id
于 2010-08-16T16:17:18.960 回答
0

我同意 JacobM 的观点,但提出了一种稍微不同的方法:

SELECT
    c.id,
    c.name, 
    SUM(co1.invoicetotal) as PREV_MONTH, 
    SUM(co2.invoicetotal) as CUR_MONTH, 
FROM
    customers as c, 
    customerorders as co1, 
    customerorders as co2
WHERE 
    c.salesrep_id = 24
    and  co1.customer_id = c.id
    and  co2.customer_id = c.id
    AND co1.orderdate BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND CURDATE()
    AND co2.orderdate > DATE_SUB(CURDATE(), INTERVAL 30 DAY)
GROUP by c.id
order by total desc

不确定哪个会更有效。

于 2010-08-16T16:40:55.067 回答