Rails中的复杂查询

时间:2017-07-23 12:25:32

标签: sql ruby-on-rails activerecord database-design

我正在尝试为VRP构建一个简单的求解器Web应用程序。我的问题是如何构建一个查询,用他的用户的用户名,经度,纬度和他的产品返回每个客户,所有产品列产品的最后库存数量?

数据库图: database scheme 客户和用户关系是一对一的(用户是客户的超类)

推销员和用户关系是一对一的(用户是推销员的超类)

销售员和客户关系是一对多的(推销员有很多客户)

客户和产品关系是一对多的(客户有很多产品)

产品和库存关系是一对多的(需要记录每次库存变化)

欢迎任何改变数据库方案的建议

3 个答案:

答案 0 :(得分:1)

实际上,您不需要为每个模型构建查询。

您可以先为客户构建一个查询:@customers = Customer.all,然后通过不同模型之间存在的关系,可以访问您想要的任何数据。

即:

查询客户的用户名,经度和latittude(以第一位客户为例,您可以使用Customer.where(:user_id => some_number).find进行查询。

customer = Customer.all.first
customer.user.username
customer.user.longtitude
customer.user.latitude

下面的查询可用于获取第一个客户的第一个产品,以及该产品的第一个库存。您可以再次使用.find.where等不同方法查询所需的确切产品和库存。

customer.products.first.stocks.first 

如果您想抓住所有客户(使用@customers = Customer.all的实例变量并遍历每个客户并输出结果,它将如下所示:

@customers.each do |customer|
 customer.username
end

答案 1 :(得分:1)

由于您的数据是以如此复杂的方式构建的,因此使用ActiveRecord对象检索的所有内容都会变得非常慢(最近出现此问题)。

让我们看看我们可以一起弄清楚什么。

由于您没有提供MySQL问题的示例数据,我自己填写,但随时可以改进数据,我们可能会找到更好的解决方案。

模式

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(6) unsigned NOT NULL,
  `username` varchar(200) NOT NULL,
  `longitude` varchar(200) NOT NULL,
   `latitude` varchar(200) NOT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `customers` (
  `id` int(6) unsigned NOT NULL,
    `user_id` int(6) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `products` (
  `id` int(6) unsigned NOT NULL,
    `customer_id` int(6) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `stocks` (
  `id` int(6) unsigned NOT NULL,
  `product_id` int(6) unsigned NOT NULL,
  `quantity` int(200) unsigned NOT NULL,
  `updated_at` DATETIME,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;

INSERT INTO `users` (`id`, `username`, `longitude`, `latitude`) VALUES
  (1, 'username1', '11.12', '22.33'),
  (2, 'username2', '11.12', '22.33'),
  (3, 'username3', '11.12', '22.33');
INSERT INTO `customers` (`id`, `user_id`) VALUES
  (9, 1),
  (10, 2),
  (11, 3);
INSERT INTO `products` (`id`, `customer_id`) VALUES
  (33, 9),
  (34, 10),
  (35, 11);
INSERT INTO `stocks` (`id`, `product_id`, `quantity`, `updated_at`) VALUES
  (1, 33, 12, '2017-07-17 13:24:01'),
  (2, 34, 1, '2017-07-17 13:24:02'),
  (3, 35, 99, '2017-07-17 13:24:03'),
  (4, 36, 3, '2017-07-17 13:31:01');

查询

SELECT users.id, username, longitude, latitude, products.id as product_id, quantity from `users`
INNER JOIN customers ON user_id = users.id
INNER JOIN products ON customer_id = customers.id
INNER JOIN stocks ON product_id = products.id
ORDER BY stocks.updated_at DESC

结果

id  username    longitude   latitude    product_id  quantity
1   username1   11.12       22.33       33          12
2   username2   11.12       22.33       34          1
3   username3   11.12       22.33       35          99

对于Rails部分,您可以使用以下内容:

data = Users.select("id, longitude etc").
  joins(
    "INNER JOIN customers ON user_id = users.id etc "
)

SQL Fiddle link

答案 2 :(得分:0)

您可以在模型类中添加方法,并使用重要的相关信息返回您需要的所有内容。快速浏览rails文档活动记录