简体   繁体   English

PostgreSQL在复杂的SQL查询中返回null

[英]PostgreSQL returns null in a complex sql query

I'm currently having a strange problem with a complex sql code. 我目前在使用复杂的sql代码时遇到一个奇怪的问题。 Here is the schema: 这是模式:

CREATE TABLE category (
  category_id  SERIAL PRIMARY KEY,
  cat_name  CHARACTER VARYING(255)
);

CREATE TABLE items (
  item_id      SERIAL PRIMARY KEY,
  category_id  INTEGER NOT NULL,
  item_name    CHARACTER VARYING(255),
  CONSTRAINT item_category_id_fk FOREIGN KEY(category_id) REFERENCES category(category_id) ON DELETE RESTRICT
);

CREATE TABLE item_prices (
  price_id     SERIAL PRIMARY KEY,
  item_id      INTEGER NOT NULL,
  price        numeric,
  CONSTRAINT item_prices_item_id_fk FOREIGN KEY(item_id) REFERENCES items(item_id) ON DELETE RESTRICT
);

INSERT INTO category(cat_name) VALUES('Category 1');
INSERT INTO category(cat_name) VALUES('Category 2');
INSERT INTO category(cat_name) VALUES('Category 3');

INSERT INTO items(category_id, item_name) VALUES(1, 'item 1');
INSERT INTO items(category_id, item_name) VALUES(1, 'item 2');
INSERT INTO items(category_id, item_name) VALUES(1, 'item 3');
INSERT INTO items(category_id, item_name) VALUES(1, 'item 4');

INSERT INTO item_prices(item_id, price) VALUES(1, '24.10');
INSERT INTO item_prices(item_id, price) VALUES(1, '26.0');
INSERT INTO item_prices(item_id, price) VALUES(1, '35.24');

INSERT INTO item_prices(item_id, price) VALUES(2, '46.10');
INSERT INTO item_prices(item_id, price) VALUES(2, '30.0');
INSERT INTO item_prices(item_id, price) VALUES(2, '86.24');

INSERT INTO item_prices(item_id, price) VALUES(3, '94.0');
INSERT INTO item_prices(item_id, price) VALUES(3, '70.24');

INSERT INTO item_prices(item_id, price) VALUES(4, '46.10');
INSERT INTO item_prices(item_id, price) VALUES(4, '30.0');
INSERT INTO item_prices(item_id, price) VALUES(4, '86.24');

Now the problem here is, I need to get an item , its category and the latest inserted item_price . 现在的问题是,我需要获取一个item ,其category和最近插入的item_price

My current query looks like this: 我当前的查询如下所示:

SELECT
  category.*,
  items.*,
  f.price
FROM items
LEFT JOIN category ON category.category_id = items.category_id
LEFT JOIN ( 
  SELECT 
    price_id, 
    item_id, 
    price 
  FROM item_prices
  ORDER BY price_id DESC
  LIMIT 1
) AS f ON f.item_id = items.item_id
WHERE items.item_id = 1

Unfortunately, the price column is returned as NULL . 不幸的是, price列返回为NULL What I don't understand is why? 我不明白为什么? The join in the query works just fine if you execute it stand-alone. 如果您独立执行查询,则查询中的联接可以正常工作。

SQLFiddle with the complex query: SQLFiddle与复杂查询:
http://sqlfiddle.com/#!1/33888/2 http://sqlfiddle.com/#!1/33888/2

SQLFiddle with the the join solo: SQLFiddle与join独奏:
http://sqlfiddle.com/#!1/33888/5 http://sqlfiddle.com/#!1/33888/5

The inner query only returns one record, which happens not to be item id #1. 内部查询仅返回一条记录,该记录恰好不是项ID#1。

The inner query is run in full, then the results of that is used "as f". 内部查询将完全运行,然后将其结果用作“ f”。

I think what you are trying to get is this: 我认为您想要得到的是:

SELECT
  category.*,
  items.*,
  f.max_price
FROM items
JOIN category ON category.category_id = items.category_id
JOIN (
  SELECT item_id,MAX(price) AS max_price FROM item_prices
  WHERE item_id=1
  GROUP BY item_id
  ) AS f ON f.item_id = items.item_id

Note that the WHERE clause is now in the inner select - there's no point getting prices for items other than (in this case) 1. These are grouped by item_id, resulting in a single row, which is item_id=1, and the most expensive price for item_id=1. 请注意,WHERE子句现在位于内部选择中-除了(在这种情况下)1之外,没有其他项目的价格是没有意义的。它们按item_id分组,导致只有一行,即item_id = 1,并且是最昂贵的item_id = 1的价格。

This data is then joined to the other two tables. 然后,此数据将连接到其他两个表。

I have changed the "LEFT JOIN" to "JOIN", since we don't want records from the other tables which don't have a corresponding record in the inner select. 我已将“ LEFT JOIN”更改为“ JOIN”,因为我们不希望其他表的记录在内部选择中没有对应的记录。

I'm not sure what the question is. 我不确定是什么问题。 The query is doing exactly what you are telling it to do. 该查询确实在执行您要执行的操作。

The inner subquery is returning the highest price id, which 11. This has an item id of 4, which doesn't match the "1" requested in the query. 内部子查询返回最高价格ID(11)。项目ID为4,与查询中请求的“ 1”不匹配。

My only reaction is: "of course the price is null, that is what the query is constructed to do". 我唯一的反应是:“当然price为空,这就是查询的构造目的”。

If you want to get the latest price for every item , you cn use Window Function since PostgreSQL supports it. 如果要获取每个item的最新价格,则可以使用Window Function因为PostgreSQL支持它。

The query below uses ROW_NUMBER() which basically generates sequence of number based on how the records will be grouped and sorted. 下面的查询使用ROW_NUMBER() ,它基本上根据记录的分组和排序方式生成数字序列。

WITH records
AS
(
    SELECT  a.item_name,
            b.cat_name,
            c.price,
            ROW_NUMBER() OVER(PARTITION BY a.item_id ORDER BY c.price_id DESC) rn
    FROM    items a
            INNER JOIN category b
                ON a.category_id = b.category_id
            INNER JOIN item_prices c
                ON a.item_id = c.item_id
)
SELECT  item_name, cat_name, price
FROM    records
WHERE   rn = 1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM