我无法在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
错误。
请提出任何建议或意见?
提前致谢。 罗布
答案 0 :(得分: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
答案 1 :(得分: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)
这完全取决于您想要获得的数据。
答案 2 :(得分: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
答案 3 :(得分:0)
OMG小马关于你为什么会遇到这个错误是正确的。在比较中使用的子查询必须始终返回单个值。
我的猜测是你需要创建两个子查询(一个用于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
答案 4 :(得分:0)
我同意雅各布的观点,但提出了一种略有不同的方法:
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
不确定哪种效率更高。