我目前遇到一个复杂的sql代码的奇怪问题。 这是架构:
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');
现在问题是,我需要获得item
,category
和最新插入的item_price
。
我当前的查询如下所示:
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
不幸的是,price
列以NULL
的形式返回。我不明白为什么?如果您单独执行查询,则查询中的连接可以正常工作。
SQLFiddle与复杂查询:
http://sqlfiddle.com/#!1/33888/2
SQLFiddle与连接独奏:
http://sqlfiddle.com/#!1/33888/5
答案 0 :(得分:1)
内部查询只返回一条记录,而不是项目编号#1。
内部查询完整运行,然后结果使用“as f”。
我认为你想要得到的是:
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
请注意,WHERE子句现在位于内部选择中 - 除了(在这种情况下)1之外的项目没有必要获得价格。这些项目按item_id分组,产生一行,即item_id = 1,并且item_id = 1最贵的价格。
然后将此数据连接到其他两个表。
我已将“LEFT JOIN”更改为“JOIN”,因为我们不希望其他表中的记录在内部选择中没有相应的记录。
答案 1 :(得分:1)
我不确定问题是什么。查询正在完成您要告诉它的操作。
内部子查询返回最高价格ID,其中11.项目ID为4,与查询中请求的“1”不匹配。
我唯一的反应是:“当然price
为空,这就是构造查询的目的”。
答案 2 :(得分:1)
如果你想获得每个item
的最新价格,你可以使用Window Function
,因为PostgreSQL支持它。
下面的查询使用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