奇怪的sql查询实现连接表

时间:2016-06-06 22:54:40

标签: sql ruby postgresql ruby-on-rails-4

我需要一些SQL查询的帮助。让我来描述一下场景

我有三个表,dispensariesgoodsproducts

products条记录有两个fkgood_iddispensary_id,可让我通过产品从药房访问商品。 商品还有一个名为name

的属性

现在我要解决的问题如下:

对于提供的一组商品名称([good_name1, good_name2, etc]),我想获得所有包含所有商品的药房(与这些商品相匹配的商品)。

让我举一个例子:

 good1 whose names is  good_1 belongs to dispensary1
 good1 whose names is  good_1 belongs to dispensary2
 good2 whose names is  good_2 belongs to dispensary1

所以我需要创建一个SQL查询,其中提供的商品数组[good1, good2]仅返回dispesary1

提前致谢。

2 个答案:

答案 0 :(得分:0)

您可能希望将其转换为一个函数,该函数接受您所追求的goods.name项的数组。首先,我会得到正确的数据语法和格式。在查询窗口中尝试以下操作,看看它是否通过静态商品列表中的文本项获取了您想要的数据。

SELECT dispensary.id, dispensary.name
FROM products
LEFT JOIN goods ON goods.id = products.goods_id
LEFT JOIN dispensary ON dispensary.id = products.dispensary_id
WHERE goods.name IN ([good_name1, good_name2, etc])
AND dispensary.id IS NOT NULL;

修改

只返回带有数组中所有项目的药房,尝试(来自@ErwinBrandstetter的修改参考回答PostgreSQL where all in array):

CREATE OR REPLACE FUNCTION f_dispensaries_with_all_products(_user_arr string[])
  RETURNS SETOF dispensary AS
$BODY$
DECLARE
    _sql text := '
    SELECT d.*
    FROM   products p
    JOIN   dispensary d ON d.id = p.dispensary_id';
    i int;
BEGIN

FOREACH i IN ARRAY _user_arr LOOP
    _sql  := _sql  || '
    JOIN   goods g' || i || ' ON g|| i || '.id = p.good_id';
END LOOP;

_sql  := _sql  || '
    WHERE  d.id IS NOT NULL ';

FOREACH i IN ARRAY _user_arr LOOP
    _sql  := _sql  || '
    AND    g' || i || '.name = ' || _user_arr[i];
END LOOP;

-- RAISE NOTICE '%', _sql;
RETURN QUERY EXECUTE _sql;

END;
$BODY$ LANGUAGE plpgsql VOLATILE;

答案 1 :(得分:0)

实现这一目标的一种方法是使用INTERSECT,为每个子句生成一个集合 - 这意味着您必须将列表展开到 n 查询中,每个项目一个:

SELECT dispensary.id, dispensary.name
FROM products
INNER JOIN goods ON goods.id = products.goods_id
INNER JOIN dispensary ON dispensary.id = products.dispensary_id
WHERE goods.name = 'good_1'
INTERSECT
SELECT dispensary.id, dispensary.name
FROM products
INNER JOIN goods ON goods.id = products.goods_id
INNER JOIN dispensary ON dispensary.id = products.dispensary_id
WHERE goods.name = 'good_2'
INTERSECT
SELECT dispensary.id, dispensary.name
FROM products
INNER JOIN goods ON goods.id = products.goods_id
INNER JOIN dispensary ON dispensary.id = products.dispensary_id
WHERE goods.name = 'good_3'

这样,您只会获得所有集合中的结果。