无法获取 mysql 子查询的头信息

发布于 2024-09-14 17:33:52 字数 1007 浏览 8 评论 0原文

我在 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 - 子查询返回超过 1 行 错误。

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

提前致谢。 抢

Im having trouble getting my head round subqueries in Mysql. Fairly simple ones are ok, and most tutorials I find rarely go beyond the typical:

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

What I am trying to pull out of my database is the following (I'll try my best to explain this without any background on our db):

Retrieve list of customers belonging to particular rep and total amount spent in last month (in one column) and amount spent in month to date, in other column.

As results, this would look roughly as follows:

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

Query I am using to get the first part of the data is the following:

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

The DATE_SUB can be replaced by actual dates, as php variables will be going here eventually. As an example this just gives me valid data.

This gives me, for example:

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

So, ideally, my subquery would be this exact same query, but with the dates changed. I keep getting a #1242 - Subquery returns more than 1 row error.

Any suggestions or advice please?

Thanks in advance.
Rob

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

抹茶夏天i‖ 2024-09-21 17:33:52
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
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
郁金香雨 2024-09-21 17:33:52

您收到错误的原因是:

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)

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

The reason you get the error is because:

WHERE column1 = (SELECT column1 FROM t2)

t2.column1 is returning more than one result, but because of the equals operator before the subquery - only one value can be accepted.

So you either need to change it to IN:

WHERE column1 IN (SELECT column1 FROM t2)

...to accept multiple values. Or change the subquery to only return one variable - this example returns the highest t2.column1 value for the entire table:

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

It all depends on what data you are trying to get.

苦行僧 2024-09-21 17:33:52

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

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 

I am leaving out the date calculations since you are generating that from code:

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 
笑,眼淚并存 2024-09-21 17:33:52

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

OMG Ponies is correct about why you got that error. Subqueries that are use in a comparison must always return a single value.

My guess is that you need to create two subqueries (one for prev and one for curr) and join them by user ID. Something like this:

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
孤云独去闲 2024-09-21 17:33:52

我同意 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

不确定哪种方法更有效。

I agree with JacobM, but came up with a slightly different approach:

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

Not sure which would be more efficient.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文