我的数据库(MySQL数据库)中的两个表如下:
forward[0] = 'a'
forward[1] = 'b'
forward[2] = 'b'
forward[3] = 'a'
forward[4] = '\0'
在“销售”表中,同一商店可以有特定月份的多个销售条目。
现在我要打印最没有的商店的名称。用户输入的月份和年份的条目。
我应该如何以高效可靠的方式实现这一目标?
答案 0 :(得分:3)
尝试按商店分组,并计算每家商店的交易数量(表A)。然后从表A获得最大数量的交易,您将获得一个数字(例如值B)。接下来,您可以复制用于获取值B的SQL,并将其放在表A中的Having子句中,如下所示:
这是表A
select count(store_id) as sid
from sales
group by store_id
这是值B
select max(sid)
from( select count(store_id) as sid
from sales
group by store_id ) t1
这是具有最大交易次数的商店的ID
select store_name, count(store_name)
from sales
group by store_name
having count(store_name) = (select max(sid)
from( select count(store_id) as sid
from sales
group by store_id ) t1)
Yo可以在where子句中添加年和月约束,并将其与stores表连接以获取store_name
select store_name, count(store_name)
from sales, stores
where sales.store_id = stores.store_id
and year(sale_date) = '2015'
and month(sale_date) = '09'
group by store_id, store_name
having count(store_name) = (select max(sid)
from( select count(store_id) as sid
from sales
where year(sale_date) = '2015'
and month(sale_date) = '09'
group by store_id ) t1)
请注意,根据销售数量重新安排商店并将解决方案限制在第一个注册表的其他解决方案可能是错误的,因为可能有多个商店具有相同数量的交易 。此查询将返回具有该销售数量的所有商店。
Pd:你可以尝试这个解决方案here。
此致
答案 1 :(得分:2)
查看我的fiddle。
SELECT s.*, COUNT(sl.store_id) AS number_of_sales
FROM stores s
JOIN sales sl ON
s.store_id = sl.store_id
AND sl.sale_date BETWEEN '2015-09-01' AND '2015-09-30'
GROUP BY s.store_id
ORDER BY number_of_sales DESC
LIMIT 1
CREATE TABLE stores (
store_id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
store_name VARCHAR(255) NOT NULL
);
CREATE TABLE sales (
sale_id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
store_id INT(11) NOT NULL REFERENCES stores(store_id),
sale_date DATE NOT NULL,
sale_amt INT(11) NOT NULL
);
/* add index on sale_date for faster search by dates */
/* if you use myisam, add index on store_id too */
ALTER TABLE sales ADD INDEX (sale_date);
/* test data */
INSERT INTO stores VALUES(1, 'shop1');
INSERT INTO stores VALUES(2, 'shop2');
INSERT INTO stores VALUES(3, 'shop3');
INSERT INTO sales (sale_id, store_id, sale_date, sale_amt) VALUES (40, 2, '2015-09-22', 31);
INSERT INTO sales (sale_id, store_id, sale_date, sale_amt) VALUES (41, 2, '2015-09-30', 74);
INSERT INTO sales (sale_id, store_id, sale_date, sale_amt) VALUES (42, 1, '2015-01-16', 212);
INSERT INTO sales (sale_id, store_id, sale_date, sale_amt) VALUES (43, 3, '2015-09-15', 113);
INSERT INTO sales (sale_id, store_id, sale_date, sale_amt) VALUES (44, 1, '2015-09-11', 61);
INSERT INTO sales (sale_id, store_id, sale_date, sale_amt) VALUES (45, 1, '2015-09-15', 49);
INSERT INTO sales (sale_id, store_id, sale_date, sale_amt) VALUES (46, 1, '2015-05-14', 28);
INSERT INTO sales (sale_id, store_id, sale_date, sale_amt) VALUES (47, 3, '2014-12-23', 102);
INSERT INTO sales (sale_id, store_id, sale_date, sale_amt) VALUES (48, 1, '2015-09-19', 101);
INSERT INTO sales (sale_id, store_id, sale_date, sale_amt) VALUES (49, 2, '2015-09-24', 131);
INSERT INTO sales (sale_id, store_id, sale_date, sale_amt) VALUES (50, 1, '2015-09-13', 155);
/*
select shop with max number of entries in 2015/April
Shop1 has 4 sales in 2015/April
Shop2 has 3 sales in 2015/April
Shop3 has 1 sale in 2015/April
*/
SELECT s.*, COUNT(sl.store_id) AS number_of_sales
FROM stores s
JOIN sales sl ON
s.store_id = sl.store_id
AND sl.sale_date BETWEEN '2015-09-01' AND '2015-09-30'
GROUP BY s.store_id
ORDER BY number_of_sales DESC
LIMIT 1
首先,查询会为每个商店选择销售,这些商店的销售额实际为JOIN
。
第二,我们通过GROUP BY
计算销售foreach商店的数量。
第三,我们按照条目数desc排序(通过ORDER BY
)分组结果,并选择一个(通过LIMIT
)最高值。
P.S。您可以将上述查询与其他答案的查询进行比较,并告诉我们结果:)
我生产了1000家商店和1000万销售额。在localhost Windows NT上测试,5.5.25a-log - MySQL社区服务器(GPL),默认为my-large.ini配置。表类型为INNODB。
使用SQL_NO_CACHE指令从3次启动中获得平均时间。
select SQL_NO_CACHE store_id, count(*)
from sales
group by store_id
having count(*) = (select max(count(*))
from sales
group by store_id)
#
1111 - 无效使用群组功能
select SQL_NO_CACHE store_name
from stores st
inner join sales sa on st.store_id = sa.store_id
where year(sale_date) = '2015'
and month(sale_date) = '09'
group by store_name
order by count(*) desc
limit 1;
此解决方案的特别说明。如果不同的商店名称相同,则其结果将分组为一个商店的结果(因为group by store_name
声明)。
SELECT SQL_NO_CACHE store_name
FROM stores
INNER JOIN
(
SELECT store_id, COUNT(*) AS cnt
FROM sales
GROUP BY store_id
WHERE sale_date BETWEEN '2015-09-01' AND '2015-09-30'
ORDER BY cnt
LIMIT 1
) max_sales ON stores.store_id = max_sales.store_id;
#1064
- 您的SQL语法出错;检查与MySQL服务器版本对应的手册,以获得正确的语法 附近' WHERE sale_date BETWEEN' 2015-09-01' AND' 2015-09-30' 按顺序排序 '在第8行
但它会剔除同名商店,但不同的商品。
如果您使用大数据并希望获得最佳性能,则需要使用precalc。构建数据库级别。首先会存储所有数据,第二个会回复用户'查询。
例如,您可以创建表格,该表格按年份和月份存储每个商店的销售额。为了使数据保持最新,您可以使用触发器。
如果你的数据不是很大,那么就不要在优化中发挥作用。一切都是用例。
答案 2 :(得分:1)
请尝试此查询。我已经通过创建您的演示数据库来检查它。
SELECT COUNT(*) AS total,
st.store_name, sl.store_id, sl.sale_date, sl.sale_amt,
YEAR(sl.sale_date) as year,
MONTH(sl.sale_date) as month
FROM stores AS st
JOIN sales AS sl ON st.store_id = sl.store_id
WHERE YEAR(sl.sale_date)='2015' and MONTH(sl.sale_date)='12'
GROUP BY st.store_id
ORDER BY total
DESC LIMIT 1
答案 3 :(得分:0)
你可以试一试:
select store_name
from stores st
inner join sales sa on st.store_id = sa.store_id
where year(sale_date) = <year entered by user>
and month(sale_date) = <month entered by user>
group by store_name
order by count(*) desc
limit 1;
您可能会因为创建一对覆盖索引而受益:
create index idx_stores_id_name on stores(store_id, store_name);
create index idx_sales_storeid_saledate on sales (store_id, sale_date);
答案 4 :(得分:0)
要有效地获得它,请在INNER JOIN
之前获得前1名store_id。这可以防止加入一对多关系。
SELECT store_name
FROM stores
INNER JOIN
(
SELECT store_id, COUNT(*) AS cnt
FROM sales
WHERE sale_date BETWEEN '2015-09-01' AND '2015-09-30'
GROUP BY store_id
ORDER BY cnt DESC
LIMIT 1
) max_sales ON stores.store_id = max_sales.store_id;
假设,至少存在以下索引:
CREATE INDEX idx1 ON sales (sale_date, store_id);
答案 5 :(得分:0)
您可以使用此查询
SELECT store_name
FROM stores
WHERE store_id = (
SELECT store_id
FROM sales
WHERE YEAR(sale_date) = '<year value>'
AND MONTH(sale_date) = '<month value>'
GROUP BY store_id
ORDER BY COUNT(*) DESC
LIMIT 1
)
这将提供所需的结果,如果数据在数据库表中更多,它将比连接更快。
答案 6 :(得分:0)
问题不是SUM(sale_amt)
吗?
SELECT
( SELECT store_name
FROM Stores
WHERE store_id = s.store_id
) AS StoreName
FROM Sales s
WHERE sale_date >= '2015-09-01'
AND sale_date < '2015-09-01' + INTERVAL 1 MONTH
GROUP BY store_id
ORDER BY SUM(sale_amt) DESC
LIMIT 1;
(不提供联系)