如何在 mysql 中使用 group by 的子查询?
How to use subquery with group by in mysql?
I have one table with multiple rows for particular users.i am having
data with many years like 2019,2018,2016 and more. i have two
scenarios:
1.i want data of particular INVOICE_YEAR.
2,but same time i want FIRST DATE OF INVOICE GENERATED FOR PARTICULAR
USER.
我的sql查询:
$yearOf
这是动态年份输入变量。
$yearOf
= 2019;
$Records = "SELECT MIN(inv.INVOICE_DATE) AS MIN_INVOICE_DATE
FROM invoices as inv
LEFT JOIN customers as cm ON cm.CUSTOMER_ID = inv.CUSTOMER_ID
where inv.INVOICE_YEAR IN (".$yearOf.")
group by inv.CUSTOMER_ID ORDER BY cm.CUSTOMER_NAME ASC";
如果我想要 INVOICE_YEAR IN ('2019') 的所有用户的数据,你可以看到我的查询。我的第一个条件将得到满足,我将获得 INVOICE_YEAR = 的所有用户数据2019.
但同时我想要第一个发票日期所以为此我使用了 MIN(inv.INVOICE_DATE)
但正如我使用的那样
where inv.INVOICE_YEAR IN (".$yearOf.")
这在 where 条件下所以它给了我特定年份的第一个发票日期。
但我希望所有用户的第一个发票日期为整个table。
我尝试使用子查询,但它显示 子查询 returns 超过 1 行的错误
我的子查询查询:
$Records = "SELECT
(
SELECT MIN(inv.INVOICE_DATE) AS MIN_INVOICE_DATE FROM invoices AS inv GROUP BY inv.CUSTOMER_ID) AS MIN_INVOICE_DATE
FROM invoices as inv
LEFT JOIN customers as cm ON cm.CUSTOMER_ID = inv.CUSTOMER_ID
where inv.INVOICE_YEAR IN (".$yearOf.")
group by inv.CUSTOMER_ID ORDER BY cm.CUSTOMER_NAME ASC";
例如:
有 3 位顾客 101,102,103
table 中的数据如下:
id | customer_id | invoice_date | invoice_year
1 | 101 | 2019-01-01 | 2019
2 | 101 | 2016-01-01 | 2016
3 | 101 | 2017-01-01 | 2017
4 | 101 | 2016-01-02 | 2016
5 | 102 | 2019-01-02 | 2019
6 | 103 | 2018-01-02 | 2018
7 | 103 | 2019-01-07 | 2019
8 | 102 | 2015-01-02 | 2015
当我请求查询以获取 INVOICE_YEAR 2019 年的数据以及特定用户的第一个发票日期时,它应该给出如下输出:
id | customer_id | invoice_date | invoice_year | min_invoice_date
1 | 101 | 2019-01-01 | 2019 | 2016-01-01
5 | 102 | 2019-01-02 | 2019 | 2015-01-02
7 | 103 | 2019-01-07 | 2019 | 2019-01-07
如我所愿所有用户的MIN_INVOICE_DATE列中的第一个发票日期。
但它显示的数据如下:
id | customer_id | invoice_date | invoice_year | min_invoice_date
1 | 101 | 2019-01-01 | 2019 | 2019-01-01
5 | 102 | 2019-01-02 | 2019 | 2019-01-02
7 | 103 | 2019-01-07 | 2019 | 2019-01-07
您想提取每个客户在 2019 年的最早发票,以及整个 table 中最早发票的日期。
在 MySQL 8.0 中,您可以使用 window 函数解决此问题:
SELECT id, customer_id, invoice_date, invoice_year, min_invoice_date
FROM (
SELECT
t.*,
ROW_NUMBER() OVER(PARTITION BY customer_id, invoice_year ORDER BY invoice_date) rn,
MIN(invoice_date) OVER(PARTITION BY customer_id) min_invoice_date
FROM mytable t
) x
WHERE invoice_year = 2019 AND rn = 1
在早期版本中,您可以:
JOIN
table 的查询计算每个客户的总体最小值 invoice_date
- 使用具有
NOT EXISTS
条件的相关子查询来筛选 2019 年最早的发票面额客户
查询:
SELECT t.id, t.customer_id, t.invoice_date, t.invoice_year, m.min_invoice_date
FROM mytable t
INNER JOIN (
SELECT customer_id, MIN(invoice_date) min_invoice_date
FROM mytable
GROUP BY customer_id
) m ON m.customer_id = t.customer_id
WHERE
t.invoice_year = 2019
AND NOT EXISTS (
SELECT 1
FROM mytable t1
WHERE t1.invoice_year = 2019
AND t1.customer_id = t.customer_id
AND t1.invoice_date < t.invoice_date
)
在这个demo on DB Fiddle中,两个查询return:
| id | customer_id | invoice_date | invoice_year | min_invoice_date |
| --- | ----------- | ------------ | ------------ | ---------------- |
| 1 | 101 | 2019-01-01 | 2019 | 2016-01-01 |
| 5 | 102 | 2019-01-02 | 2019 | 2015-01-02 |
| 7 | 103 | 2019-01-07 | 2019 | 2018-01-02 |
我猜测您希望查看每个日历年每个客户的第一张(最早日期的)发票的详细信息。您希望该结果过滤为仅涵盖一年。
因此,从子查询开始查找每个日历年每个客户的第一张发票的日期。 (https://www.db-fiddle.com/f/bmBZ14Vr9Re6ahpfs2FF2X/0)
SELECT MIN(invoice_date) first_invoice_date,
YEAR(invoice_date) calendar_year,
customer_id
FROM invoices
GROUP BY YEAR(invoice_date), customer_id
然后通过将该子查询连接到您的原始 invoices
table 来检索这些发票的详细信息。 (https://www.db-fiddle.com/f/bmBZ14Vr9Re6ahpfs2FF2X/1)
SELECT invoices.*
FROM invoices
JOIN (
SELECT MIN(invoice_date) first_invoice_date,
YEAR(invoice_date) calendar_year,
customer_id
FROM invoices
GROUP BY YEAR(invoice_date), customer_id
) firsts
ON invoices.customer_id = firsts.customer_id
AND invoices.invoice_date = firsts.first_invoice_date
ORDER BY invoices.customer_id,
invoices.invoice_year,
invoices.invoice_date
然后,输入 WHERE invoices.invoice_year = 2019
以获得您想要的年份。
请注意,您的 invoice_year
列是不必要的,因为它始终可以从 YEAR(invoice_date)
计算得出。你应该考虑摆脱它。
I have one table with multiple rows for particular users.i am having data with many years like 2019,2018,2016 and more. i have two scenarios:
1.i want data of particular INVOICE_YEAR.
2,but same time i want FIRST DATE OF INVOICE GENERATED FOR PARTICULAR USER.
我的sql查询:
$yearOf
这是动态年份输入变量。
$yearOf
= 2019;
$Records = "SELECT MIN(inv.INVOICE_DATE) AS MIN_INVOICE_DATE
FROM invoices as inv
LEFT JOIN customers as cm ON cm.CUSTOMER_ID = inv.CUSTOMER_ID
where inv.INVOICE_YEAR IN (".$yearOf.")
group by inv.CUSTOMER_ID ORDER BY cm.CUSTOMER_NAME ASC";
如果我想要 INVOICE_YEAR IN ('2019') 的所有用户的数据,你可以看到我的查询。我的第一个条件将得到满足,我将获得 INVOICE_YEAR = 的所有用户数据2019.
但同时我想要第一个发票日期所以为此我使用了 MIN(inv.INVOICE_DATE)
但正如我使用的那样
where inv.INVOICE_YEAR IN (".$yearOf.")
这在 where 条件下所以它给了我特定年份的第一个发票日期。
但我希望所有用户的第一个发票日期为整个table。
我尝试使用子查询,但它显示 子查询 returns 超过 1 行的错误
我的子查询查询:
$Records = "SELECT
(
SELECT MIN(inv.INVOICE_DATE) AS MIN_INVOICE_DATE FROM invoices AS inv GROUP BY inv.CUSTOMER_ID) AS MIN_INVOICE_DATE
FROM invoices as inv
LEFT JOIN customers as cm ON cm.CUSTOMER_ID = inv.CUSTOMER_ID
where inv.INVOICE_YEAR IN (".$yearOf.")
group by inv.CUSTOMER_ID ORDER BY cm.CUSTOMER_NAME ASC";
例如:
有 3 位顾客 101,102,103
table 中的数据如下:
id | customer_id | invoice_date | invoice_year
1 | 101 | 2019-01-01 | 2019
2 | 101 | 2016-01-01 | 2016
3 | 101 | 2017-01-01 | 2017
4 | 101 | 2016-01-02 | 2016
5 | 102 | 2019-01-02 | 2019
6 | 103 | 2018-01-02 | 2018
7 | 103 | 2019-01-07 | 2019
8 | 102 | 2015-01-02 | 2015
当我请求查询以获取 INVOICE_YEAR 2019 年的数据以及特定用户的第一个发票日期时,它应该给出如下输出:
id | customer_id | invoice_date | invoice_year | min_invoice_date
1 | 101 | 2019-01-01 | 2019 | 2016-01-01
5 | 102 | 2019-01-02 | 2019 | 2015-01-02
7 | 103 | 2019-01-07 | 2019 | 2019-01-07
如我所愿所有用户的MIN_INVOICE_DATE列中的第一个发票日期。
但它显示的数据如下:
id | customer_id | invoice_date | invoice_year | min_invoice_date
1 | 101 | 2019-01-01 | 2019 | 2019-01-01
5 | 102 | 2019-01-02 | 2019 | 2019-01-02
7 | 103 | 2019-01-07 | 2019 | 2019-01-07
您想提取每个客户在 2019 年的最早发票,以及整个 table 中最早发票的日期。
在 MySQL 8.0 中,您可以使用 window 函数解决此问题:
SELECT id, customer_id, invoice_date, invoice_year, min_invoice_date
FROM (
SELECT
t.*,
ROW_NUMBER() OVER(PARTITION BY customer_id, invoice_year ORDER BY invoice_date) rn,
MIN(invoice_date) OVER(PARTITION BY customer_id) min_invoice_date
FROM mytable t
) x
WHERE invoice_year = 2019 AND rn = 1
在早期版本中,您可以:
JOIN
table 的查询计算每个客户的总体最小值invoice_date
- 使用具有
NOT EXISTS
条件的相关子查询来筛选 2019 年最早的发票面额客户
查询:
SELECT t.id, t.customer_id, t.invoice_date, t.invoice_year, m.min_invoice_date
FROM mytable t
INNER JOIN (
SELECT customer_id, MIN(invoice_date) min_invoice_date
FROM mytable
GROUP BY customer_id
) m ON m.customer_id = t.customer_id
WHERE
t.invoice_year = 2019
AND NOT EXISTS (
SELECT 1
FROM mytable t1
WHERE t1.invoice_year = 2019
AND t1.customer_id = t.customer_id
AND t1.invoice_date < t.invoice_date
)
在这个demo on DB Fiddle中,两个查询return:
| id | customer_id | invoice_date | invoice_year | min_invoice_date |
| --- | ----------- | ------------ | ------------ | ---------------- |
| 1 | 101 | 2019-01-01 | 2019 | 2016-01-01 |
| 5 | 102 | 2019-01-02 | 2019 | 2015-01-02 |
| 7 | 103 | 2019-01-07 | 2019 | 2018-01-02 |
我猜测您希望查看每个日历年每个客户的第一张(最早日期的)发票的详细信息。您希望该结果过滤为仅涵盖一年。
因此,从子查询开始查找每个日历年每个客户的第一张发票的日期。 (https://www.db-fiddle.com/f/bmBZ14Vr9Re6ahpfs2FF2X/0)
SELECT MIN(invoice_date) first_invoice_date,
YEAR(invoice_date) calendar_year,
customer_id
FROM invoices
GROUP BY YEAR(invoice_date), customer_id
然后通过将该子查询连接到您的原始 invoices
table 来检索这些发票的详细信息。 (https://www.db-fiddle.com/f/bmBZ14Vr9Re6ahpfs2FF2X/1)
SELECT invoices.*
FROM invoices
JOIN (
SELECT MIN(invoice_date) first_invoice_date,
YEAR(invoice_date) calendar_year,
customer_id
FROM invoices
GROUP BY YEAR(invoice_date), customer_id
) firsts
ON invoices.customer_id = firsts.customer_id
AND invoices.invoice_date = firsts.first_invoice_date
ORDER BY invoices.customer_id,
invoices.invoice_year,
invoices.invoice_date
然后,输入 WHERE invoices.invoice_year = 2019
以获得您想要的年份。
请注意,您的 invoice_year
列是不必要的,因为它始终可以从 YEAR(invoice_date)
计算得出。你应该考虑摆脱它。