2017-07-29 183 views
2

我想从第二查询重写第一个查询结果的结果:联合查询上一列不同

SELECT "panel_restaurants_restaurant"."id", 
     "panel_restaurants_restaurant"."name", 
     "panel_restaurants_restaurant"."logo", 
     "panel_restaurants_restaurantfeatures"."currency" AS "currency", 
     ST_DistanceSphere(location, ST_GeomFromText('POINT(0.0 0.0)',4326)) AS "distance", 
     "panel_meals_meal"."id" AS "meal_id", 
     "panel_meals_meal"."status" AS "meal_status", 
     "panel_meals_meal"."available_count" AS "available_dishes", 
     "panel_meals_meal"."discount_price" AS "discount_price", 
     "panel_meals_meal"."normal_price" AS "normal_price", 
     "panel_meals_meal"."collection_from" AS "pickup_from", 
     "panel_meals_meal"."collection_to" AS "pickup_to", 
     "panel_meals_meal"."description" AS "meal_description" 
FROM "panel_restaurants_restaurant" 
INNER JOIN "panel_restaurants_restaurantfeatures" ON (
    "panel_restaurants_restaurantfeatures"."restaurant_id" = "panel_restaurants_restaurant"."id") 
LEFT OUTER JOIN "panel_meals_meal" ON ("panel_restaurants_restaurant"."id" = "panel_meals_meal"."restaurant_id" 
       AND "panel_meals_meal"."status" = 0 
       AND (
       ("panel_meals_meal"."collection_from" AT TIME ZONE 'Europe/Warsaw')::date = DATE 'today' OR 
       ("panel_meals_meal"."collection_from" AT TIME ZONE 'Europe/Warsaw')::date = DATE 'tomorrow' 
       ) 
       AND "panel_meals_meal"."collection_to" > '2017-07-29 19:33:47.992075+00:00' 
       AND "panel_meals_meal"."available_count" > 0) 
WHERE "panel_restaurants_restaurant"."status" = 2 
UNION 
SELECT "panel_restaurants_restaurant"."id", 
     "panel_restaurants_restaurant"."name", 
     "panel_restaurants_restaurant"."logo", 
     "panel_restaurants_restaurantfeatures"."currency" AS "currency", 
     ST_DistanceSphere(location, ST_GeomFromText('POINT(0.0 0.0)',4326)) AS "distance", 
     "panel_meals_meal"."id" AS "meal_id", 
     "panel_meals_meal"."status" AS "meal_status", 
     "panel_meals_meal"."initial_count" AS "available_dishes", 
     "panel_meals_meal"."discount_price" AS "discount_price", 
     "panel_meals_meal"."normal_price" AS "normal_price", 
     "panel_meals_meal"."collection_from" AS "pickup_from", 
     "panel_meals_meal"."collection_to" AS "pickup_to", 
     "panel_meals_meal"."description" AS "meal_description" 
FROM "panel_restaurants_restaurant" 
INNER JOIN "panel_restaurants_restaurantfeatures" ON (
     "panel_restaurants_restaurantfeatures"."restaurant_id" = "panel_restaurants_restaurant"."id") 
LEFT OUTER JOIN "panel_meals_meal" ON (
    "panel_restaurants_restaurant"."id" = "panel_meals_meal"."restaurant_id" AND 
    "panel_meals_meal"."status" = 0) 
INNER JOIN "panel_meals_mealrepeater" ON (
    "panel_meals_mealrepeater"."meal_id" = "panel_meals_meal"."id") 
WHERE "panel_restaurants_restaurant"."status" = 2 AND "panel_meals_mealrepeater"."saturday" = true 
ORDER BY distance ASC 

例如 - 第一查询可能返回空值什么来自panel_meals_meal表,但第二个将返回一些东西 - 在这种情况下,对于所有其他值,我将具有相同的值id,name,logo,currency,distance和不同的值(从第一个查询返回的空值,以及从另一个返回的something)。

所以问题是 - 我如何使这个UNION在一定范围的列上不同(实际上只有一个就足够了 - id)?

回答

3

您可以通过FULL OUTER JOIN而不是UNION进行所需的操作,并使用COALESCE来获得您的优势。

我简化您的方案以专注于FULL OUTER JOIN部分:

这是表(把它们作为结果你第一SELECT前磨片UNIONSELECT后说UNION):

CREATE TABLE table_a 
(
    id INTEGER NOT NULL PRIMARY KEY, 
    name TEXT, 
    logo TEXT 
) ; 
CREATE TABLE table_b 
(
    id INTEGER NOT NULL PRIMARY KEY, 
    name TEXT, 
    logo TEXT 
) ; 

这些都是我们在其中的数据:

INSERT INTO 
    table_a 
    (id, name, logo) 
VALUES 
    (1, 'Name1-A', 'Logo1-A'), 
    (2, NULL, NULL), 
    (3, 'Name3-A', NULL), 
    (4, NULL, 'Logo4-A'), 
    (5, 'Name5-only-in-A', NULL); 

INSERT INTO 
    table_b 
    (id, name, logo) 
VALUES 
    (1, 'Name1-B', 'Logo1-B'), 
    (2, 'Name2-B', NULL), 
    (3, 'Name3-B', 'Logo3-B'), 
    (4, 'Name4-B', 'Logo4-B'), 
    (6, 'Name6-only-in-B', 'Logo6-B'); 

你要找的是在您检索所有来自table_atable_b行这样的方式加入进行查询。然后,您可以使用:

SELECT 
    id, 
    COALESCE(a.name, b.name) AS name, 
    COALESCE(a.logo, b.logo) AS logo 
FROM 
    table_a AS a 
    FULL OUTER JOIN table_b AS b USING(id) 
ORDER BY 
    id ; 
 
id | name   | logo 
-: | :-------------- | :------ 
1 | Name1-A   | Logo1-A 
2 | Name2-B   | null 
3 | Name3-A   | Logo3-B 
4 | Name4-B   | Logo4-A 
5 | Name5-only-in-A | null 
6 | Name6-only-in-B | Logo6-B 

dbfiddle here


在你的情况下,通过完整的第一(SELECT ...) AS a,与同为b替代table_a AS a。我假设id是你的主键。

参考文献:

+0

这样的作品,但它发现了另一个意想不到的行为。现在,如果两者都选择返回数据,则结果包含重复项:( –

+0

不,这种情况下,它们不会;这由'JOIN ... USING(id)'处理。没有任何'id'的重复,即使它们中的一些在两个表中。 – joanolo

+0

我不知道,也许这是因为您在示例中使用了两个单独的表格,而且我选择了相同的表格,但是我的结果集包含重复项目。 –