[英]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.