我正在使用在线提供的Yelp数据集。我已经尝试优化查询几天了。对于下面要列出的架构,我需要构造一个查询以提供以下内容:
以下是架构:
CREATE TABLE business(
bid varchar(40) PRIMARY KEY,
name varchar(100),
city varchar(40),
state char(2),
zip varchar(10),
latitude real,
longitude real,
address varchar(100),
numreviews INTEGER DEFAULT 0,
numcheckins INTEGER DEFAULT 0,
avgreview float DEFAULT 0,
isopen bool,
stars float
);
CREATE TABLE users(
uid varchar(40) PRIMARY KEY,
name varchar(40),
avgstars float,
fans INTEGER,
coolvotes INTEGER,
reviewcount INTEGER,
funnyvotes INTEGER,
signup varchar(20),
usefulvotes INTEGER,
latitude real,
longitude real
);
CREATE TABLE reviews(
rid varchar(40) PRIMARY KEY,
bid varchar(40),
uid varchar(40),
stars float,
date varchar(20),
funny INTEGER,
useful INTEGER,
cool INTEGER,
text varchar(1024),
FOREIGN KEY (uid) REFERENCES users(uid),
FOREIGN KEY (bid) REFERENCES business(bid)
);
CREATE TABLE friends(
uid varchar(40) REFERENCES users(uid),
fid varchar(40) REFERENCES users(uid)
);
对于每个用户的朋友,我显示以下内容:
当前,这是我成功的唯一“解决方案”。
步骤1:获取每个用户朋友的所有ID的列表。
SELECT fid from friends where uid = '{userId}'
这将返回每个用户朋友的所有用户ID的列表。所以我基本上有一个朋友ID列表。
第2步:有了这些信息,我在程序中对该列表运行了foreach
循环。对于朋友ID列表的每次迭代,我执行以下查询并为循环的当前迭代提供临时朋友ID:
SELECT U.name, B.name, B.city, R.text, R.date FROM reviews as R, users as U, business as B
WHERE U.uid = '{currentFriendId}'
AND R.uid = '{currentFriendId}'
AND B.bid = R.bid
AND date = (SELECT MAX(date) FROM reviews WHERE uid = '{currentFriendId}')
每次运行此for循环时,我都会得到一行所需的输出,例如:
这很好...除了我必须为用户的每个朋友运行此查询。这是非常昂贵的。
目标:我正在尝试合并这两个查询,或者对其进行彻底修改,以在单个查询中一次生成所有行。
问题:鉴于提供的信息,我该如何解决我的查询以通过单个查询生成所有这些信息?
答案 0 :(得分:1)
这似乎是每个组的前n个问题。
一种方法是使用横向连接。
确保在../Inc (should be by default)
../Drivers/CMSIS/Device/ST/STM32F4xx/Include (should be by default)
../Drivers/STM32F4xx_HAL_Driver/Inc (should be by default)
../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy (should be by default)
../Drivers/CMSIS/Include (should be by default)
"${workspace_loc:/${ProjName}/Drivers/Device/ST/STM32F4xx/Include}"
"${workspace_loc:/${ProjName}/Drivers/CMSIS/Core/Include}"
"${workspace_loc:/${ProjName}/Drivers/CMSIS/Core_A/Include}"
"${workspace_loc:/${ProjName}/Drivers/CMSIS/DSP/Include}"
的{{1}}表上有索引。综合索引。一个索引按此顺序在两列上。
类似这样的东西:
reviews
查询
(uid, date)
答案 1 :(得分:0)
这应该很好。
SELECT name FROM employees as E
WHERE E.uid IN (SELECT uid FROM employees WHERE name = 'John')
您不需要像单个真值匹配查询那样进行相等的比较。
答案 2 :(得分:0)
跟着Manos的回答,我不确定我为什么要限制每个fid的原因
SELECT U.name, B.name, B.city, R.text, R.date
FROM business AS B
INNER JOIN reviews AS R ON B.bid = R.bid
INNER JOIN users AS U ON R.uid = U.uid
WHERE (R.date = (SELECT MAX(X.date) FROM reviews AS X WHERE X.uid = R.uid))
AND (R.uid IN (SELECT fid FROM friends));
如果您的问题是查询仅在一行中显示,则应删除该 where uid = 以获取所有uid的结果。
答案 3 :(得分:0)
我也和Vladimir Baranov大致在同一时间得到了答案,但是我也会发布我的版本。我不保证它很漂亮:
SELECT R.name as user_name, B.name as business_name, B.City, R.text
FROM (SELECT bid, name, text
FROM (SELECT R.rid, R.bid, R.uid, R.text, max_date
FROM reviews as R INNER JOIN
(SELECT uid, MAX(date) as max_date FROM reviews WHERE uid IN (SELECT fid from friends where uid = 'BfcNxKpnF9z5wJLXY7elRg') GROUP BY uid) sub
ON R.uid = sub.uid AND R.date = sub.max_date) as review_info
INNER JOIN users
on review_info.uid = users.uid) as R
INNER JOIN business as B
ON R.bid = B.bid
答案 4 :(得分:-1)
检查您发布的架构后,我使用MySQL创建数据库并使用以下示例数据填充表:
INSERT INTO users (uid, name) VALUES
('user1', 'user1 name'),
('user2', 'user2 name'),
('user3', 'user3 name'),
('user4', 'user4 name'),
('user5', 'user5 name');
INSERT INTO friends (uid, fid) VALUES
('user1', 'user2'), ('user1', 'user3'),
('user2', 'user4'), ('user2', 'user5');
INSERT INTO business (bid, name, city) VALUES
('b1', 'business 1', 'city 1'),
('b2', 'business 2', 'city 2'),
('b3', 'business 3', 'city 3'),
('b4', 'business 4', 'city 4');
INSERT INTO reviews (rid, bid, uid, stars, date, text) VALUES
('r1', 'b1', 'user1', 5, '2019-05-01', 'blah'),
('r2', 'b2', 'user1', 5, '2019-05-02', 'blah'),
('r3', 'b3', 'user1', 5, '2019-05-03', 'blah'),
('r4', 'b1', 'user2', 4, '2019-05-11', 'blah'),
('r5', 'b2', 'user3', 3, '2019-05-12', 'blah'),
('r6', 'b1', 'user4', 5, '2019-05-13', 'blah');
这使我可以通过在MySQL Workbench中执行查询来验证我提出的原始解决方案是否正确。 我假设您提到的“失败完成”与查询本身无关,而是您使用的数据库连接api的暂时失败。 请注意,该代码已更新,以纳入Mihail Shishkov提出的使用参数的建议。
-- Display review information originating from friends of user1
-- DECLARE @UID varchar(40); -- Uncomment for MS-SQL (variables need to be declared)
SET @UID = 'user1';
SELECT U.name, B.name, B.city, R.text, R.date
FROM business AS B
INNER JOIN reviews AS R ON B.bid = R.bid
INNER JOIN users AS U ON R.uid = U.uid
WHERE (R.date = (SELECT MAX(X.date) FROM reviews AS X WHERE (X.uid = R.uid)))
AND (R.uid IN (SELECT F.fid FROM friends AS F WHERE (F.uid = @UID)));
基于示例数据,并使用' user1 '作为@UID参数的值,查询结果为:
name name city text date
------------------------------------------------
user2 name business 1 city 1 blah 2019-05-11
user3 name business 2 city 2 blah 2019-05-12
此外,我假设在您的架构上下文中(如在现实世界中)友谊是一种双向关系,这意味着“ user1”和“ user2”之间的友谊仅需通过带有值('user1','user2')和 reverse ('user2','user1')的表'friends'是不必要的。 因此,出于完整性考虑,您可以使用以下查询:
-- Display review information originating from friends of user2
SET @UID = 'user2';
SELECT U.name, B.name, B.city, R.text, R.date
FROM business AS B
INNER JOIN reviews AS R ON B.bid = R.bid
INNER JOIN users AS U ON R.uid = U.uid
WHERE (R.date = (SELECT MAX(X.date) FROM reviews AS X WHERE (X.uid = R.uid)))
AND (R.uid IN (SELECT F.fid FROM friends AS F WHERE (F.uid = @UID) UNION
SELECT F.uid FROM friends AS F WHERE (F.fid = @UID)));
现在,使用' user2 '作为@UID参数的值和查询的扩展版本,我们获得以下结果:
name name city text date
------------------------------------------------
user1 name business 3 city 3 blah 2019-05-03
user4 name business 1 city 1 blah 2019-05-13
如果您认为答案是可以接受的,我将不胜感激。